Model widgets do not follow data-minimum-input-length
mfrasca opened this issue · comments
Describe the bug
Model widgets don't seem to set nor use the data-minimum-input-length
value. data is requested via ajax even on empty input.
Code Snippet
class AccessionForm(forms.ModelForm):
class Meta:
model = Accession
fields = ['code', 'received_quantity', 'received_type', 'source', 'accessioned_date', 'received_date', ]
widgets = {
'source': s2forms.ModelSelect2Widget(model=Contact,
search_fields=['name__icontains']),
'received_type': s2forms.Select2Widget,
}
produces (edited for easier reading)
<select name="source" data-ajax--cache="true"
class="django-select2 django-select2-heavy select2-hidden-accessible"
data-ajax--type="GET" data-minimum-input-length="0" data-ajax--url="/select2/fields/auto.json"
data-field_id="MTQwMjI4MDg1OTcxODgw:1hNiFv:rQwuma5lz_zSWcYWZ--FJsNPGu0"
data-allow-clear="true" id="id_source" data-placeholder="" tabindex="-1" aria-hidden="true"
style="width: 100%;">
<option value=""></option>
</select>
which is not what I expect, since this is a "heavy" widget, and it should get a "2" minimum length value. so I edit with the code
$('select.django-select2-heavy').attr('data-minimum-input-length', '2')
and still the query is executed even on empty input, or less than length 1:
[06/May/2019 18:24:51] "GET /select2/fields/auto.json?field_id=MTQwMjI4MDg1OTcxODgw%3A1hNiFv%3ArQwuma5lz_zSWcYWZ--FJsNPGu0 HTTP/1.1" 200 271
[06/May/2019 18:24:52] "GET /select2/fields/auto.json?term=m&field_id=MTQwMjI4MDg1OTcxODgw%3A1hNiFv%3ArQwuma5lz_zSWcYWZ--FJsNPGu0 HTTP/1.1" 200 152
Hi @mfrasca good catch, that is a bug in
django-select2/django_select2/forms.py
Line 240 in 2bb6f3a
If you use setdefault
twice, it does not overwrite.
>>> a = {}
>>> a.setdefault('foo', 'bar')
'bar'
>>> a.setdefault('foo', 'baz')
'bar'
>>> a
{'foo': 'bar'}
Since you found the bug, would you care to fix it and submit a PR?
so your code is applying defaults while collecting them. I'll have a look.
so your code is applying defaults while collecting them. I'll have a look.
Yes, correct. Excellent catch, everyone seems to have ignored that issue before.
is this a correct test?
@@ -315,6 +315,17 @@ class TestModelSelect2Mixin(TestHeavySelect2Mixin):
widget.queryset = Genre.objects.all()
assert isinstance(widget.get_queryset(), QuerySet)
+ def test_tag_attrs(self):
+ widget = ModelSelect2Widget(queryset=Genre.objects.all(), search_fields=['title__icontains'])
+ output = widget.render('name', 'value')
+ assert 'data-minimum-input-length="2"' in output
+
+ def test_custom_tag_attrs(self):
+ widget = ModelSelect2Widget(
+ 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
+
def test_get_search_fields(self):
widget = ModelSelect2Widget()
with pytest.raises(NotImplementedError):
@mfrasca yes that does look correct, however I would add tests for all sub classes of Select2Mixin
, Select2TagMixin
and HeavySelect2Mixin
, since they all are supposed to have different defaults for data-minimum-input-length
.
I'll have a look then. I will create a new pull request containing the additional tests, then we can work on polishing them, making them succeed, so you can merge the PR.
(just a useless remark about "everyone seems to have ignored", my experience at office, while I was still working in a office, is that most of my colleagues fetched free software, judged it as if it were a black box, and behaved as if shopping, or if they do find a bug and fix it, they mostly did not consider providing feedback.) (Giorgio Gaber in his song "La Libertà": "… la libertà è partecipazione.")
why does this one look different than the others?
def build_attrs(self, *args, **kwargs):
"""Add select2's tag attributes."""
print('data-minimum-input-length was {} when setting to 1'.format(self.attrs.get('data-minimum-input-length')))
self.attrs.setdefault('data-minimum-input-length', 1)
self.attrs.setdefault('data-tags', 'true')
self.attrs.setdefault('data-token-separators', '[",", " "]')
return super(Select2TagMixin, self).build_attrs(*args, **kwargs)
you're namely writing into self.attrs
, while the other build_attrs
work on a 'floating' variable, and I've not yet seen where you use that and write into self.attrs