Fixes #260 -- Normalize choices keys and selected choices to strings

This commit is contained in:
Damir Arbula 2016-02-23 12:50:04 +01:00 committed by Johannes Hoppe
parent a8a4baf04d
commit 9ed8f58fa6
7 changed files with 46 additions and 8 deletions

View File

@ -1,6 +1,9 @@
Changelog Summary
=================
### v5.8.2
* Fixes #260 -- Fixes bug in render choices
### v5.8.0
* Changed signature of `render` and `render_choices` to satisfy Django 1.10 changes.
* Changed widgets' inheritance tree to be more consistent.

View File

@ -9,4 +9,4 @@ The app includes Select2 driven Django Widgets and Form Fields.
"""
__version__ = "5.8.1"
__version__ = "5.8.2"

View File

@ -247,8 +247,8 @@ class HeavySelect2Mixin(object):
else:
choices = self.choices
output = ['<option></option>' if not self.is_required else '']
choices = {(k, v) for k, v in choices if k in selected_choices}
selected_choices = {force_text(v) for v in selected_choices}
choices = {(k, v) for k, v in choices if force_text(k) in selected_choices}
for option_value, option_label in choices:
output.append(self.render_option(selected_choices, option_value, option_label))
return '\n'.join(output)
@ -409,6 +409,7 @@ class ModelSelect2Mixin(object):
choices = chain(self.choices, choices)
else:
choices = self.choices
selected_choices = {force_text(v) for v in selected_choices}
output = ['<option></option>' if not self.is_required else '']
if isinstance(self.choices, ModelChoiceIterator):
if not self.queryset:
@ -418,8 +419,7 @@ class ModelSelect2Mixin(object):
choices = {(obj.pk, self.label_from_instance(obj))
for obj in self.choices.queryset.filter(pk__in=selected_choices)}
else:
choices = {(k, v) for k, v in choices if k in selected_choices}
selected_choices = {force_text(v) for v in selected_choices}
choices = {(k, v) for k, v in choices if force_text(k) in selected_choices}
for option_value, option_label in choices:
output.append(self.render_option(selected_choices, option_value, option_label))
return '\n'.join(output)

View File

@ -14,8 +14,8 @@ from six import text_type
from django_select2.cache import cache
from django_select2.forms import (
HeavySelect2Widget, ModelSelect2TagWidget, ModelSelect2Widget,
Select2Widget
HeavySelect2MultipleWidget, HeavySelect2Widget, ModelSelect2TagWidget,
ModelSelect2Widget, Select2Widget
)
from tests.testapp import forms
from tests.testapp.forms import (
@ -301,3 +301,26 @@ class TestHeavySelect2TagWidget(TestHeavySelect2Mixin):
queryset=Genre.objects.all(), search_fields=['title__icontains'], attrs={'data-minimum-input-length': '3'})
output = widget.render('name', 'value')
assert 'data-minimum-input-length="3"' in output
class TestHeavySelect2MultipleWidget(object):
url = reverse('heavy_select2_multiple_widget')
form = forms.HeavySelect2MultipleWidgetForm()
widget_cls = HeavySelect2MultipleWidget
def test_widgets_selected_after_validation_error(self, db, live_server, driver):
driver.get(live_server + self.url)
title = driver.find_element_by_id('id_title')
title.send_keys('fo')
genres, fartists = driver.find_elements_by_css_selector('.select2-selection--multiple')
genres.click()
genres.send_keys('o') # results are Zero One Two Four
# select second element - One
driver.find_element_by_css_selector('.select2-results li:nth-child(2)').click()
genres.submit()
# there is a ValidationError raised, check for it
errstring = driver.find_element_by_css_selector('ul.errorlist li').text
assert errstring == "Title must have more than 3 characters."
# genres should still have One as selected option
result_title = driver.find_element_by_css_selector('.select2-selection--multiple li').get_attribute('title')
assert result_title == 'One'

View File

@ -144,14 +144,22 @@ class HeavySelect2WidgetForm(forms.Form):
class HeavySelect2MultipleWidgetForm(forms.Form):
title = forms.CharField(max_length=50)
genres = forms.MultipleChoiceField(
widget=HeavySelect2MultipleWidget(data_view='heavy_data_1', choices=NUMBER_CHOICES)
widget=HeavySelect2MultipleWidget(data_view='heavy_data_1', choices=NUMBER_CHOICES),
choices=NUMBER_CHOICES
)
featured_artists = forms.MultipleChoiceField(
widget=HeavySelect2MultipleWidget(data_view='heavy_data_2', choices=NUMBER_CHOICES),
choices=NUMBER_CHOICES,
required=False
)
def clean_title(self):
if len(self.cleaned_data['title']) < 3:
raise forms.ValidationError("Title must have more than 3 characters.")
return self.cleaned_data["title"]
class ModelSelect2TagWidgetForm(forms.ModelForm):
class Meta:

View File

@ -15,7 +15,7 @@ urlpatterns = [
url(r'^heavy_select2_widget/$',
TemplateFormView.as_view(form_class=HeavySelect2WidgetForm), name='heavy_select2_widget'),
url(r'^heavy_select2_multiple_widget/$',
TemplateFormView.as_view(form_class=HeavySelect2MultipleWidgetForm),
TemplateFormView.as_view(form_class=HeavySelect2MultipleWidgetForm, success_url='/'),
name='heavy_select2_multiple_widget'),
url(r'^model_select2_widget/$',

View File

@ -12,12 +12,16 @@ class TemplateFormView(FormView):
def heavy_data_1(request):
term = request.GET.get("term", "")
numbers = ['Zero', 'One', 'Two', 'Three', 'Four', 'Five']
numbers = filter(lambda num: term.lower() in num.lower(), numbers)
results = [{'id': index, 'text': value} for (index, value) in enumerate(numbers)]
return HttpResponse(json.dumps({'err': 'nil', 'results': results}), content_type='application/json')
def heavy_data_2(request):
term = request.GET.get("term", "")
numbers = ['Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Fortytwo']
numbers = filter(lambda num: term.lower() in num.lower(), numbers)
results = [{'id': index, 'text': value} for (index, value) in enumerate(numbers)]
return HttpResponse(json.dumps({'err': 'nil', 'results': results}), content_type='application/json')