Fixes #260 -- Normalize choices keys and selected choices to strings
This commit is contained in:
parent
a8a4baf04d
commit
9ed8f58fa6
|
@ -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.
|
||||
|
|
|
@ -9,4 +9,4 @@ The app includes Select2 driven Django Widgets and Form Fields.
|
|||
|
||||
"""
|
||||
|
||||
__version__ = "5.8.1"
|
||||
__version__ = "5.8.2"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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/$',
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue