Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEW] multiple select field with other field support. #113

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions example/app/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@

from django.contrib import admin

from .forms import BookForm
from .models import Book


class BookAdmin(admin.ModelAdmin):
form = BookForm
list_display = ('title', 'categories', 'tags', 'published_in')


Expand Down
1 change: 1 addition & 0 deletions example/app/fixtures/app_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"title": "My book 1",
"tags": "sex,work,happy",
"categories": "1,3,5",
"tabs_with_other": "sex,|other_option",
"published_in": "BC,AL,AK",
"chapters": "1"
}
Expand Down
9 changes: 9 additions & 0 deletions example/app/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django import forms

from .models import Book


class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = '__all__'
24 changes: 24 additions & 0 deletions example/app/migrations/0002_auto_20200421_0403.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 3.0.5 on 2020-04-21 09:03

from django.db import migrations
import multiselectfield.db.fields


class Migration(migrations.Migration):

dependencies = [
('app', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='book',
name='tabs_with_other',
field=multiselectfield.db.fields.MultiSelectWithOtherField(blank=True, choices=[('sex', 'Sex'), ('work', 'Work'), ('happy', 'Happy'), ('food', 'Food'), ('field', 'Field'), ('boring', 'Boring'), ('interesting', 'Interesting'), ('huge', 'Huge'), ('nice', 'Nice'), ('other', 'Other')], max_length=154, null=True),
),
migrations.AlterField(
model_name='book',
name='published_in',
field=multiselectfield.db.fields.MultiSelectField(choices=[('Canada - Provinces', (('AB', 'Alberta'), ('BC', 'British Columbia'))), ('USA - States', (('AK', 'Alaska'), ('AL', 'Alabama'), ('AZ', 'Arizona')))], max_length=31, verbose_name='Province or State'),
),
]
22 changes: 13 additions & 9 deletions example/app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from django.utils.translation import gettext as _

from multiselectfield import MultiSelectField
from multiselectfield.db.fields import MultiSelectWithOtherField

CATEGORY_CHOICES = (
(1, _('Handbooks and manuals by discipline')),
Expand All @@ -35,15 +36,15 @@
)

TAGS_CHOICES = (
('sex', _('Sex')), # noqa: E241
('work', _('Work')), # noqa: E241
('happy', _('Happy')), # noqa: E241
('food', _('Food')), # noqa: E241
('field', _('Field')), # noqa: E241
('boring', _('Boring')), # noqa: E241
('sex', _('Sex')), # noqa: E241
('work', _('Work')), # noqa: E241
('happy', _('Happy')), # noqa: E241
('food', _('Food')), # noqa: E241
('field', _('Field')), # noqa: E241
('boring', _('Boring')), # noqa: E241
('interesting', _('Interesting')), # noqa: E241
('huge', _('Huge')), # noqa: E241
('nice', _('Nice')), # noqa: E241
('huge', _('Huge')), # noqa: E241
('nice', _('Nice')), # noqa: E241
)

PROVINCES = (
Expand All @@ -59,7 +60,7 @@

PROVINCES_AND_STATES = (
(_("Canada - Provinces"), PROVINCES),
(_("USA - States"), STATES), # noqa: E241
(_("USA - States"), STATES), # noqa: E241
)


Expand All @@ -76,6 +77,9 @@ class Book(models.Model):
max_choices=2)
chapters = MultiSelectField(choices=CHAPTER_CHOICES, default=ONE)

tabs_with_other = MultiSelectWithOtherField(choices=TAGS_CHOICES, other_max_length=100,
null=True, blank=True, min_choices=1, max_choices=2)

def __str__(self):
return self.title

Expand Down
44 changes: 32 additions & 12 deletions example/app/test_msf.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
else:
u = str


if VERSION < (1, 9):
def get_field(model, name):
return model._meta.get_field_by_name(name)[0]
Expand All @@ -40,7 +39,6 @@ def get_field(model, name):


class MultiSelectTestCase(TestCase):

fixtures = ['app_data.json']
maxDiff = 4000

Expand Down Expand Up @@ -69,6 +67,7 @@ def test_filter(self):
def test_values_list(self):
tag_list_list = Book.objects.all().values_list('tags', flat=True)
categories_list_list = Book.objects.all().values_list('categories', flat=True)
tabs_with_other_list_list = Book.objects.all().values_list('tabs_with_other', flat=True)

# Workaround for Django bug #9619
# https://code.djangoproject.com/ticket/9619
Expand All @@ -79,18 +78,27 @@ def test_values_list(self):
if VERSION >= (1, 6) and VERSION < (1, 8):
self.assertStringEqual(tag_list_list, [u('sex,work,happy')])
self.assertStringEqual(categories_list_list, [u('1,3,5')])
self.assertStringEqual(tabs_with_other_list_list, [u('sex,other_option')])
else:
self.assertListEqual(tag_list_list, [['sex', 'work', 'happy']])
self.assertListEqual(categories_list_list, [['1', '3', '5']])
self.assertListEqual(tabs_with_other_list_list, [['sex', 'other_option']])

def test_form(self):
form_class = modelform_factory(Book, fields=('title', 'tags', 'categories'))
self.assertEqual(len(form_class.base_fields), 3)
form_class = modelform_factory(Book, fields=('title', 'tags', 'categories', 'tabs_with_other'))
self.assertEqual(len(form_class.base_fields), 4)
form = form_class({'title': 'new book',
'categories': '1,2'})
'categories': '1,2', 'tabs_with_other': 'sex,other_option'})
if form.is_valid():
form.save()

def test_form_invalid(self):
form_class = modelform_factory(Book, fields=('title', 'tags', 'categories', 'tabs_with_other'))
self.assertEqual(len(form_class.base_fields), 4)
form = form_class({'title': 'new book',
'categories': '1,2', 'tabs_with_other': 'sex,work,other_option'})
self.assertFalse(form.is_valid())

def test_empty_update(self):
book = Book.objects.get(id=1)
self.assertEqual(book.get_chapters_list(), ["Chapter I"])
Expand All @@ -116,8 +124,12 @@ def test_object(self):
book = Book.objects.get(id=1)
self.assertEqual(book.get_tags_display(), 'Sex, Work, Happy')
self.assertEqual(book.get_tags_list(), ['Sex', 'Work', 'Happy'])
self.assertEqual(book.get_categories_display(), 'Handbooks and manuals by discipline, Books of literary criticism, Books about literature')
self.assertEqual(book.get_categories_list(), ['Handbooks and manuals by discipline', 'Books of literary criticism', 'Books about literature'])
self.assertEqual(book.get_categories_display(),
'Handbooks and manuals by discipline, Books of literary criticism, Books about literature')
self.assertEqual(book.get_categories_list(),
['Handbooks and manuals by discipline', 'Books of literary criticism',
'Books about literature'])
self.assertEqual(book.get_tabs_with_other_display(), 'Sex, other_option')

self.assertEqual(book.get_tags_list(), book.get_tags_display().split(', '))
self.assertEqual(book.get_categories_list(), book.get_categories_display().split(', '))
Expand All @@ -143,10 +155,17 @@ def test_validate(self):
except ValidationError:
pass

try:
get_field(Book, 'tabs_with_other').clean(['sex', 'work', 'other_option'], book)
raise AssertionError()
except ValidationError:
pass

def test_serializer(self):
book = Book.objects.get(id=1)
self.assertEqual(get_field(Book, 'tags').value_to_string(book), 'sex,work,happy')
self.assertEqual(get_field(Book, 'categories').value_to_string(book), '1,3,5')
self.assertEqual(get_field(Book, 'tabs_with_other').value_to_string(book), 'sex,|other_option')

def test_flatchoices(self):
self.assertEqual(get_field(Book, 'published_in').flatchoices, list(PROVINCES + STATES))
Expand All @@ -159,11 +178,12 @@ def test_named_groups_form(self):
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>""")
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 (1, 11) <= VERSION:
Expand Down
Loading