Add tests for named groups
This commit is contained in:
parent
203411c3cf
commit
95a47c7d22
5 changed files with 85 additions and 57 deletions
44
.travis.yml
44
.travis.yml
|
@ -7,45 +7,45 @@ python:
|
||||||
- "3.4"
|
- "3.4"
|
||||||
- "3.5"
|
- "3.5"
|
||||||
env:
|
env:
|
||||||
- DJANGO=1.4
|
- DJANGO=1.4.22
|
||||||
- DJANGO=1.5
|
- DJANGO=1.5.12
|
||||||
- DJANGO=1.6
|
- DJANGO=1.6.11
|
||||||
- DJANGO=1.7
|
- DJANGO=1.7.11
|
||||||
- DJANGO=1.8
|
- DJANGO=1.8.14
|
||||||
- DJANGO=1.9
|
- DJANGO=1.9.9
|
||||||
- DJANGO=1.10
|
- DJANGO=1.10.1
|
||||||
matrix:
|
matrix:
|
||||||
exclude:
|
exclude:
|
||||||
- python: "2.6"
|
- python: "2.6"
|
||||||
env: DJANGO=1.7
|
env: DJANGO=1.7.11
|
||||||
- python: "2.6"
|
- python: "2.6"
|
||||||
env: DJANGO=1.8
|
env: DJANGO=1.8.14
|
||||||
- python: "2.6"
|
- python: "2.6"
|
||||||
env: DJANGO=1.9
|
env: DJANGO=1.9.9
|
||||||
- python: "2.6"
|
- python: "2.6"
|
||||||
env: DJANGO=1.10
|
env: DJANGO=1.10.1
|
||||||
- python: "3.3"
|
- python: "3.3"
|
||||||
env: DJANGO=1.4
|
env: DJANGO=1.4.22
|
||||||
- python: "3.4"
|
- python: "3.4"
|
||||||
env: DJANGO=1.4
|
env: DJANGO=1.4.22
|
||||||
- python: "3.5"
|
- python: "3.5"
|
||||||
env: DJANGO=1.4
|
env: DJANGO=1.4.22
|
||||||
- python: "3.3"
|
- python: "3.3"
|
||||||
env: DJANGO=1.5
|
env: DJANGO=1.5.12
|
||||||
- python: "3.4"
|
- python: "3.4"
|
||||||
env: DJANGO=1.5
|
env: DJANGO=1.5.12
|
||||||
- python: "3.5"
|
- python: "3.5"
|
||||||
env: DJANGO=1.5
|
env: DJANGO=1.5.12
|
||||||
- python: "3.4"
|
- python: "3.4"
|
||||||
env: DJANGO=1.6
|
env: DJANGO=1.6.11
|
||||||
- python: "3.5"
|
- python: "3.5"
|
||||||
env: DJANGO=1.6
|
env: DJANGO=1.6.11
|
||||||
- python: "3.5"
|
- python: "3.5"
|
||||||
env: DJANGO=1.7
|
env: DJANGO=1.7.11
|
||||||
- python: "3.3"
|
- python: "3.3"
|
||||||
env: DJANGO=1.9
|
env: DJANGO=1.9.9
|
||||||
- python: "3.3"
|
- python: "3.3"
|
||||||
env: DJANGO=1.10
|
env: DJANGO=1.10.1
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install -q Django==$DJANGO
|
- pip install -q Django==$DJANGO
|
||||||
|
|
19
README.rst
19
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 <http://djangosnippets.org/snippets/1200/>`_.
|
This egg is inspired by this `snippet <http://djangosnippets.org/snippets/1200/>`_.
|
||||||
|
|
||||||
|
Supported Python versions: 2.6, 2.7, 3.3+
|
||||||
|
|
||||||
|
Supported Django versions: 1.4-1.0+
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
|
@ -75,11 +79,15 @@ Only you need it, if you want the translation of django-multiselectfield
|
||||||
Known Bugs and Limitations
|
Known Bugs and Limitations
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
Only in Django 1.6 and 1.7, due to `Django bug #9619 <https://code.djangoproject.com/ticket/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 <https://github.com/goinnn/django-multiselectfield/pull/30#issue-52149983>`_ 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 <https://github.com/goinnn/django-multiselectfield/issues/40>`_ for discussion about this bug.
|
2. Only in Django 1.6 and 1.7, due to `Django bug #9619 <https://code.djangoproject.com/ticket/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 <https://github.com/goinnn/django-multiselectfield/issues/40>`_ for discussion about this bug.
|
||||||
|
|
||||||
|
|
||||||
Development
|
Development
|
||||||
|
@ -96,11 +104,10 @@ of its git repository:
|
||||||
Example project
|
Example project
|
||||||
===============
|
===============
|
||||||
|
|
||||||
In the source tree, you will find a directory called `example <https://github.com/goinnn/django-multiselectfield/tree/master/example/>`_. It contains
|
There is a fully configured example project in the `example directory <https://github.com/goinnn/django-multiselectfield/tree/master/example/>`_. You can run it as usual:
|
||||||
a readily setup project that uses django-multiselectfield. You can run it as usual:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
.. 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 loaddata app_data
|
||||||
python manage.py runserver
|
python manage.py runserver
|
||||||
|
|
|
@ -20,11 +20,11 @@ from django.utils.translation import gettext as _
|
||||||
from multiselectfield import MultiSelectField
|
from multiselectfield import MultiSelectField
|
||||||
|
|
||||||
CATEGORY_CHOICES = (
|
CATEGORY_CHOICES = (
|
||||||
(1, 'Handbooks and manuals by discipline'),
|
(1, _('Handbooks and manuals by discipline')),
|
||||||
(2, 'Business books'),
|
(2, _('Business books')),
|
||||||
(3, 'Books of literary criticism'),
|
(3, _('Books of literary criticism')),
|
||||||
(4, 'Books about literary theory'),
|
(4, _('Books about literary theory')),
|
||||||
(5, 'Books about literature')
|
(5, _('Books about literature')),
|
||||||
)
|
)
|
||||||
|
|
||||||
TAGS_CHOICES = (
|
TAGS_CHOICES = (
|
||||||
|
@ -64,7 +64,9 @@ class Book(models.Model):
|
||||||
default=1)
|
default=1)
|
||||||
tags = MultiSelectField(choices=TAGS_CHOICES,
|
tags = MultiSelectField(choices=TAGS_CHOICES,
|
||||||
null=True, blank=True)
|
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):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
|
|
@ -23,7 +23,7 @@ from django.test import TestCase
|
||||||
|
|
||||||
from multiselectfield.utils import get_max_length
|
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,):
|
if sys.version_info < (3,):
|
||||||
|
@ -43,6 +43,7 @@ else:
|
||||||
class MultiSelectTestCase(TestCase):
|
class MultiSelectTestCase(TestCase):
|
||||||
|
|
||||||
fixtures = ['app_data.json']
|
fixtures = ['app_data.json']
|
||||||
|
maxDiff = 4000
|
||||||
|
|
||||||
def assertListEqual(self, left, right, msg=None):
|
def assertListEqual(self, left, right, msg=None):
|
||||||
if sys.version_info >= (3, 2):
|
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')
|
self.assertEqual(get_field(Book, 'categories').value_to_string(book), '1,3,5')
|
||||||
|
|
||||||
def test_flatchoices(self):
|
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))
|
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("""<p><label for="id_published_in_0">Province or State:</label> <ul id="id_published_in"><li>Canada - Provinces<ul id="id_published_in_0"><li><label for="id_published_in_0_0"><input id="id_published_in_0_0" name="published_in" type="checkbox" value="AB" /> Alberta</label></li>\n"""
|
||||||
|
"""<li><label for="id_published_in_0_1"><input checked="checked" id="id_published_in_0_1" name="published_in" type="checkbox" value="BC" /> British Columbia</label></li></ul></li>\n"""
|
||||||
|
"""<li>USA - States<ul id="id_published_in_1"><li><label for="id_published_in_1_0"><input checked="checked" id="id_published_in_1_0" name="published_in" type="checkbox" value="AK" /> Alaska</label></li>\n"""
|
||||||
|
"""<li><label for="id_published_in_1_1"><input id="id_published_in_1_1" name="published_in" type="checkbox" value="AL" /> Alabama</label></li>\n"""
|
||||||
|
"""<li><label for="id_published_in_1_2"><input id="id_published_in_1_2" name="published_in" type="checkbox" value="AZ" /> Arizona</label></li></ul></li></ul></p>""")
|
||||||
|
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):
|
class MultiSelectUtilsTestCase(TestCase):
|
||||||
def test_get_max_length_max_length_is_not_none(self):
|
def test_get_max_length_max_length_is_not_none(self):
|
||||||
|
|
40
tox.ini
40
tox.ini
|
@ -14,7 +14,7 @@ install_command =
|
||||||
[testenv:py26-dj14]
|
[testenv:py26-dj14]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
deps =
|
deps =
|
||||||
django==1.4.10
|
django==1.4.22
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -22,7 +22,7 @@ deps =
|
||||||
[testenv:py26-dj15]
|
[testenv:py26-dj15]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
deps =
|
deps =
|
||||||
django==1.5.5
|
django==1.5.12
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -30,7 +30,7 @@ deps =
|
||||||
[testenv:py26-dj16]
|
[testenv:py26-dj16]
|
||||||
basepython = python2.6
|
basepython = python2.6
|
||||||
deps =
|
deps =
|
||||||
django==1.6
|
django==1.6.11
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -39,7 +39,7 @@ deps =
|
||||||
[testenv:py27-dj14]
|
[testenv:py27-dj14]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps =
|
deps =
|
||||||
django==1.4.10
|
django==1.4.22
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -47,7 +47,7 @@ deps =
|
||||||
[testenv:py27-dj15]
|
[testenv:py27-dj15]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps =
|
deps =
|
||||||
django==1.5.5
|
django==1.5.12
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -55,7 +55,7 @@ deps =
|
||||||
[testenv:py27-dj16]
|
[testenv:py27-dj16]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps =
|
deps =
|
||||||
django==1.6
|
django==1.6.11
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -63,7 +63,7 @@ deps =
|
||||||
[testenv:py27-dj17]
|
[testenv:py27-dj17]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps =
|
deps =
|
||||||
django==1.7
|
django==1.7.11
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -71,7 +71,7 @@ deps =
|
||||||
[testenv:py27-dj18]
|
[testenv:py27-dj18]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps =
|
deps =
|
||||||
django==1.8
|
django==1.8.14
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -79,7 +79,7 @@ deps =
|
||||||
[testenv:py27-dj19]
|
[testenv:py27-dj19]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps =
|
deps =
|
||||||
django==1.9
|
django==1.9.9
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -87,7 +87,7 @@ deps =
|
||||||
[testenv:py27-dj110]
|
[testenv:py27-dj110]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
deps =
|
deps =
|
||||||
django==1.10
|
django==1.10.1
|
||||||
pillow==1.7.8
|
pillow==1.7.8
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -96,7 +96,7 @@ deps =
|
||||||
[testenv:py33-dj16]
|
[testenv:py33-dj16]
|
||||||
basepython = python3.3
|
basepython = python3.3
|
||||||
deps =
|
deps =
|
||||||
django==1.6
|
django==1.6.11
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -104,7 +104,7 @@ deps =
|
||||||
[testenv:py33-dj17]
|
[testenv:py33-dj17]
|
||||||
basepython = python3.3
|
basepython = python3.3
|
||||||
deps =
|
deps =
|
||||||
django==1.7
|
django==1.7.11
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -112,7 +112,7 @@ deps =
|
||||||
[testenv:py33-dj18]
|
[testenv:py33-dj18]
|
||||||
basepython = python3.3
|
basepython = python3.3
|
||||||
deps =
|
deps =
|
||||||
django==1.8
|
django==1.8.14
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -121,7 +121,7 @@ deps =
|
||||||
[testenv:py34-dj17]
|
[testenv:py34-dj17]
|
||||||
basepython = python3.4
|
basepython = python3.4
|
||||||
deps =
|
deps =
|
||||||
django==1.7
|
django==1.7.11
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -129,7 +129,7 @@ deps =
|
||||||
[testenv:py34-dj18]
|
[testenv:py34-dj18]
|
||||||
basepython = python3.4
|
basepython = python3.4
|
||||||
deps =
|
deps =
|
||||||
django==1.8
|
django==1.8.14
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -137,7 +137,7 @@ deps =
|
||||||
[testenv:py34-dj19]
|
[testenv:py34-dj19]
|
||||||
basepython = python3.4
|
basepython = python3.4
|
||||||
deps =
|
deps =
|
||||||
django==1.9
|
django==1.9.9
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -145,7 +145,7 @@ deps =
|
||||||
[testenv:py34-dj110]
|
[testenv:py34-dj110]
|
||||||
basepython = python3.4
|
basepython = python3.4
|
||||||
deps =
|
deps =
|
||||||
django==1.10
|
django==1.10.1
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -154,7 +154,7 @@ deps =
|
||||||
[testenv:py35-dj18]
|
[testenv:py35-dj18]
|
||||||
basepython = python3.5
|
basepython = python3.5
|
||||||
deps =
|
deps =
|
||||||
django==1.8
|
django==1.8.14
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -162,7 +162,7 @@ deps =
|
||||||
[testenv:py35-dj19]
|
[testenv:py35-dj19]
|
||||||
basepython = python3.5
|
basepython = python3.5
|
||||||
deps =
|
deps =
|
||||||
django==1.9
|
django==1.9.9
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
@ -170,7 +170,7 @@ deps =
|
||||||
[testenv:py35-dj110]
|
[testenv:py35-dj110]
|
||||||
basepython = python3.5
|
basepython = python3.5
|
||||||
deps =
|
deps =
|
||||||
django==1.10
|
django==1.10.1
|
||||||
pillow==2.1.0
|
pillow==2.1.0
|
||||||
PyYAML==3.10
|
PyYAML==3.10
|
||||||
coveralls==0.3
|
coveralls==0.3
|
||||||
|
|
Loading…
Reference in a new issue