From 95a47c7d220ca6c43f7da72da1617abaa0b45972 Mon Sep 17 00:00:00 2001 From: Drew Hubl Date: Fri, 23 Sep 2016 05:55:08 -0600 Subject: [PATCH] Add tests for named groups --- .travis.yml | 44 ++++++++++++++++++++--------------------- README.rst | 19 ++++++++++++------ example/app/models.py | 14 +++++++------ example/app/test_msf.py | 25 ++++++++++++++++++++--- tox.ini | 40 ++++++++++++++++++------------------- 5 files changed, 85 insertions(+), 57 deletions(-) diff --git a/.travis.yml b/.travis.yml index 506375f..39be073 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,45 +7,45 @@ python: - "3.4" - "3.5" env: - - DJANGO=1.4 - - DJANGO=1.5 - - DJANGO=1.6 - - DJANGO=1.7 - - DJANGO=1.8 - - DJANGO=1.9 - - DJANGO=1.10 + - DJANGO=1.4.22 + - DJANGO=1.5.12 + - DJANGO=1.6.11 + - DJANGO=1.7.11 + - DJANGO=1.8.14 + - DJANGO=1.9.9 + - DJANGO=1.10.1 matrix: exclude: - python: "2.6" - env: DJANGO=1.7 + env: DJANGO=1.7.11 - python: "2.6" - env: DJANGO=1.8 + env: DJANGO=1.8.14 - python: "2.6" - env: DJANGO=1.9 + env: DJANGO=1.9.9 - python: "2.6" - env: DJANGO=1.10 + env: DJANGO=1.10.1 - python: "3.3" - env: DJANGO=1.4 + env: DJANGO=1.4.22 - python: "3.4" - env: DJANGO=1.4 + env: DJANGO=1.4.22 - python: "3.5" - env: DJANGO=1.4 + env: DJANGO=1.4.22 - python: "3.3" - env: DJANGO=1.5 + env: DJANGO=1.5.12 - python: "3.4" - env: DJANGO=1.5 + env: DJANGO=1.5.12 - python: "3.5" - env: DJANGO=1.5 + env: DJANGO=1.5.12 - python: "3.4" - env: DJANGO=1.6 + env: DJANGO=1.6.11 - python: "3.5" - env: DJANGO=1.6 + env: DJANGO=1.6.11 - python: "3.5" - env: DJANGO=1.7 + env: DJANGO=1.7.11 - python: "3.3" - env: DJANGO=1.9 + env: DJANGO=1.9.9 - python: "3.3" - env: DJANGO=1.10 + env: DJANGO=1.10.1 install: - pip install -q Django==$DJANGO diff --git a/README.rst b/README.rst index a1ca3a5..6ac48dc 100644 --- a/README.rst +++ b/README.rst @@ -17,6 +17,10 @@ A new model field and form field. With this you can get a multiple select from a This egg is inspired by this `snippet `_. +Supported Python versions: 2.6, 2.7, 3.3+ + +Supported Django versions: 1.4-1.0+ + Installation ============ @@ -75,11 +79,15 @@ Only you need it, if you want the translation of django-multiselectfield Known Bugs and Limitations ========================== -Only in Django 1.6 and 1.7, due to `Django bug #9619 `_, passing a MultiSelectField to ``values()`` or ``values_list()`` will return the database representation of the field (a string of comma-separated values). The workaround is to manually call ``.split(',')`` on the result. +All tests pass on Django 1.4, 1.5, and 1.8+, so if you can, use a modern version of Django. However, if you must use Django 1.6 or 1.7 there are two known issues you will need to be aware of: -The Django bug was introduced in Django 1.6 and is fixed in Django 1.8 and onward, so ``values()`` and ``values_list()`` return a vanilla Python list of values for Django <= 1.5 and Django >= 1.8. +1. `Named groups `_ do not render properly in Django 1.6. The workaround is to manually render the field in your form or use a custom widget. If your workaround is suitably generic, please submit a pull request with it. -See `issue #40 `_ for discussion about this bug. +2. Only in Django 1.6 and 1.7, due to `Django bug #9619 `_, passing a MultiSelectField to ``values()`` or ``values_list()`` will return the database representation of the field (a string of comma-separated values). The workaround is to manually call ``.split(',')`` on the result. + + The Django bug was introduced in Django 1.6 and is fixed in Django 1.8 and onward, so ``values()`` and ``values_list()`` return a vanilla Python list of values for Django <= 1.5 and Django >= 1.8. + + See `issue #40 `_ for discussion about this bug. Development @@ -96,11 +104,10 @@ of its git repository: Example project =============== -In the source tree, you will find a directory called `example `_. It contains -a readily setup project that uses django-multiselectfield. You can run it as usual: +There is a fully configured example project in the `example directory `_. You can run it as usual: .. code-block:: bash - python manage.py syncdb --noinput + python manage.py migrate # or python manage.py syncdb --noinput python manage.py loaddata app_data python manage.py runserver diff --git a/example/app/models.py b/example/app/models.py index 1cca15e..5d9eecd 100644 --- a/example/app/models.py +++ b/example/app/models.py @@ -20,11 +20,11 @@ from django.utils.translation import gettext as _ from multiselectfield import MultiSelectField CATEGORY_CHOICES = ( - (1, 'Handbooks and manuals by discipline'), - (2, 'Business books'), - (3, 'Books of literary criticism'), - (4, 'Books about literary theory'), - (5, 'Books about literature') + (1, _('Handbooks and manuals by discipline')), + (2, _('Business books')), + (3, _('Books of literary criticism')), + (4, _('Books about literary theory')), + (5, _('Books about literature')), ) TAGS_CHOICES = ( @@ -64,7 +64,9 @@ class Book(models.Model): default=1) tags = MultiSelectField(choices=TAGS_CHOICES, null=True, blank=True) - published_in = MultiSelectField(_("Province or State"), max_length=2, choices=PROVINCES_AND_STATES) + published_in = MultiSelectField(_("Province or State"), + choices=PROVINCES_AND_STATES, + max_choices=2) def __str__(self): return self.title diff --git a/example/app/test_msf.py b/example/app/test_msf.py index ca18852..831d52b 100644 --- a/example/app/test_msf.py +++ b/example/app/test_msf.py @@ -23,7 +23,7 @@ from django.test import TestCase from multiselectfield.utils import get_max_length -from .models import Book, PROVINCES, STATES +from .models import Book, PROVINCES, STATES, PROVINCES_AND_STATES if sys.version_info < (3,): @@ -43,6 +43,7 @@ else: class MultiSelectTestCase(TestCase): fixtures = ['app_data.json'] + maxDiff = 4000 def assertListEqual(self, left, right, msg=None): if sys.version_info >= (3, 2): @@ -128,10 +129,28 @@ class MultiSelectTestCase(TestCase): self.assertEqual(get_field(Book, 'categories').value_to_string(book), '1,3,5') def test_flatchoices(self): - #raise Exception(Book._meta.get_field('published_in').flatchoices) - # raise Exception(Book.published_in.flatchoices) self.assertEqual(get_field(Book, 'published_in').flatchoices, list(PROVINCES+STATES)) + def test_named_groups(self): + self.assertEqual(get_field(Book, 'published_in').choices, PROVINCES_AND_STATES) + + def test_named_groups_form(self): + form_class = modelform_factory(Book, fields=('published_in',)) + self.assertEqual(len(form_class.base_fields), 1) + form = form_class(initial={'published_in': ['BC', 'AK']}) + + expected_html = u("""

  • Canada - Provinces
    • \n""" + """
  • \n""" + """
  • USA - States
    • \n""" + """
    • \n""" + """

""") + actual_html = form.as_p() + + if VERSION < (1, 6) or VERSION >= (1, 7): + # Django 1.6 renders the Python repr() for each group (eg: tuples + # with HTML entities), so we skip the test for that version + self.assertEqual(expected_html.replace('\n', ''), actual_html.replace('\n', '')) + class MultiSelectUtilsTestCase(TestCase): def test_get_max_length_max_length_is_not_none(self): diff --git a/tox.ini b/tox.ini index bf4297c..2a0ec2b 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ install_command = [testenv:py26-dj14] basepython = python2.6 deps = - django==1.4.10 + django==1.4.22 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -22,7 +22,7 @@ deps = [testenv:py26-dj15] basepython = python2.6 deps = - django==1.5.5 + django==1.5.12 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -30,7 +30,7 @@ deps = [testenv:py26-dj16] basepython = python2.6 deps = - django==1.6 + django==1.6.11 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -39,7 +39,7 @@ deps = [testenv:py27-dj14] basepython = python2.7 deps = - django==1.4.10 + django==1.4.22 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -47,7 +47,7 @@ deps = [testenv:py27-dj15] basepython = python2.7 deps = - django==1.5.5 + django==1.5.12 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -55,7 +55,7 @@ deps = [testenv:py27-dj16] basepython = python2.7 deps = - django==1.6 + django==1.6.11 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -63,7 +63,7 @@ deps = [testenv:py27-dj17] basepython = python2.7 deps = - django==1.7 + django==1.7.11 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -71,7 +71,7 @@ deps = [testenv:py27-dj18] basepython = python2.7 deps = - django==1.8 + django==1.8.14 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -79,7 +79,7 @@ deps = [testenv:py27-dj19] basepython = python2.7 deps = - django==1.9 + django==1.9.9 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -87,7 +87,7 @@ deps = [testenv:py27-dj110] basepython = python2.7 deps = - django==1.10 + django==1.10.1 pillow==1.7.8 PyYAML==3.10 coveralls==0.3 @@ -96,7 +96,7 @@ deps = [testenv:py33-dj16] basepython = python3.3 deps = - django==1.6 + django==1.6.11 pillow==2.1.0 PyYAML==3.10 coveralls==0.3 @@ -104,7 +104,7 @@ deps = [testenv:py33-dj17] basepython = python3.3 deps = - django==1.7 + django==1.7.11 pillow==2.1.0 PyYAML==3.10 coveralls==0.3 @@ -112,7 +112,7 @@ deps = [testenv:py33-dj18] basepython = python3.3 deps = - django==1.8 + django==1.8.14 pillow==2.1.0 PyYAML==3.10 coveralls==0.3 @@ -121,7 +121,7 @@ deps = [testenv:py34-dj17] basepython = python3.4 deps = - django==1.7 + django==1.7.11 pillow==2.1.0 PyYAML==3.10 coveralls==0.3 @@ -129,7 +129,7 @@ deps = [testenv:py34-dj18] basepython = python3.4 deps = - django==1.8 + django==1.8.14 pillow==2.1.0 PyYAML==3.10 coveralls==0.3 @@ -137,7 +137,7 @@ deps = [testenv:py34-dj19] basepython = python3.4 deps = - django==1.9 + django==1.9.9 pillow==2.1.0 PyYAML==3.10 coveralls==0.3 @@ -145,7 +145,7 @@ deps = [testenv:py34-dj110] basepython = python3.4 deps = - django==1.10 + django==1.10.1 pillow==2.1.0 PyYAML==3.10 coveralls==0.3 @@ -154,7 +154,7 @@ deps = [testenv:py35-dj18] basepython = python3.5 deps = - django==1.8 + django==1.8.14 pillow==2.1.0 PyYAML==3.10 coveralls==0.3 @@ -162,7 +162,7 @@ deps = [testenv:py35-dj19] basepython = python3.5 deps = - django==1.9 + django==1.9.9 pillow==2.1.0 PyYAML==3.10 coveralls==0.3 @@ -170,7 +170,7 @@ deps = [testenv:py35-dj110] basepython = python3.5 deps = - django==1.10 + django==1.10.1 pillow==2.1.0 PyYAML==3.10 coveralls==0.3