summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBaptiste Mispelon <bmispelon@gmail.com>2014-11-12 21:18:11 +0100
committerBaptiste Mispelon <bmispelon@gmail.com>2014-11-12 22:46:00 +0100
commit606c57a132a1e1e680853c014efc41110ee75a80 (patch)
treede1d9fd7067c715924f56f315e8444fbcd6aef70
parent3e0d7de8a6380c5747717cf32166864a22f258d5 (diff)
[1.7.x] Fixed #23795 -- Fixed a regression in custom form fields
Custom form fields having a `queryset` attribute but no `limit_choices_to` could no longer be used in ModelForms. Refs #2445. Thanks to artscoop for the report. Backport of bfb11b95626f39e2f5e18d97d7761c6f93dcc1a9 from master. Conflicts: django/forms/fields.py
-rw-r--r--django/forms/fields.py11
-rw-r--r--django/forms/models.py17
-rw-r--r--docs/releases/1.7.2.txt4
-rw-r--r--tests/model_forms/tests.py19
4 files changed, 36 insertions, 15 deletions
diff --git a/django/forms/fields.py b/django/forms/fields.py
index 011cb7762b..f686b34a09 100644
--- a/django/forms/fields.py
+++ b/django/forms/fields.py
@@ -171,17 +171,6 @@ class Field(object):
"""
return {}
- def get_limit_choices_to(self):
- """
- Returns ``limit_choices_to`` for this form field.
-
- If it is a callable, it will be invoked and the result will be
- returned.
- """
- if callable(self.limit_choices_to):
- return self.limit_choices_to()
- return self.limit_choices_to
-
def _has_changed(self, initial, data):
"""
Return True if data differs from initial.
diff --git a/django/forms/models.py b/django/forms/models.py
index 0f21a43655..16cc459175 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -329,11 +329,9 @@ class BaseModelForm(BaseForm):
# Apply ``limit_choices_to`` to each field.
for field_name in self.fields:
formfield = self.fields[field_name]
- if hasattr(formfield, 'queryset'):
- limit_choices_to = formfield.limit_choices_to
+ if hasattr(formfield, 'queryset') and hasattr(formfield, 'get_limit_choices_to'):
+ limit_choices_to = formfield.get_limit_choices_to()
if limit_choices_to is not None:
- if callable(limit_choices_to):
- limit_choices_to = limit_choices_to()
formfield.queryset = formfield.queryset.complex_filter(limit_choices_to)
def _get_validation_exclusions(self):
@@ -1118,6 +1116,17 @@ class ModelChoiceField(ChoiceField):
self.choice_cache = None
self.to_field_name = to_field_name
+ def get_limit_choices_to(self):
+ """
+ Returns ``limit_choices_to`` for this form field.
+
+ If it is a callable, it will be invoked and the result will be
+ returned.
+ """
+ if callable(self.limit_choices_to):
+ return self.limit_choices_to()
+ return self.limit_choices_to
+
def __deepcopy__(self, memo):
result = super(ChoiceField, self).__deepcopy__(memo)
# Need to force a new ModelChoiceIterator to be created, bug #11183
diff --git a/docs/releases/1.7.2.txt b/docs/releases/1.7.2.txt
index 3d9a74616b..207b7d2a0c 100644
--- a/docs/releases/1.7.2.txt
+++ b/docs/releases/1.7.2.txt
@@ -52,3 +52,7 @@ Bugfixes
* Fixed a migration serializing bug involving ``float("nan")`` and
``float("inf")`` (:ticket:23770:).
+
+* Fixed a regression where custom form fields having a ``queryset`` attribute
+ but no ``limit_choices_to`` could not be used in a
+ :class:`~django.forms.ModelForm` (:ticket:`23795`).
diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py
index eaf0c57863..2b342db744 100644
--- a/tests/model_forms/tests.py
+++ b/tests/model_forms/tests.py
@@ -2345,6 +2345,17 @@ class StumpJokeForm(forms.ModelForm):
fields = '__all__'
+class CustomFieldWithQuerysetButNoLimitChoicesTo(forms.Field):
+ queryset = 42
+
+
+class StumpJokeWithCustomFieldForm(forms.ModelForm):
+ custom = CustomFieldWithQuerysetButNoLimitChoicesTo()
+ class Meta:
+ model = StumpJoke
+ fields = () # We don't need any fields from the model
+
+
class LimitChoicesToTest(TestCase):
"""
Tests the functionality of ``limit_choices_to``.
@@ -2375,6 +2386,14 @@ class LimitChoicesToTest(TestCase):
self.assertIn(self.threepwood, stumpjokeform.fields['has_fooled_today'].queryset)
self.assertNotIn(self.marley, stumpjokeform.fields['has_fooled_today'].queryset)
+ def test_custom_field_with_queryset_but_no_limit_choices_to(self):
+ """
+ Regression test for #23795: Make sure a custom field with a `queryset`
+ attribute but no `limit_choices_to` still works.
+ """
+ f = StumpJokeWithCustomFieldForm()
+ self.assertEqual(f.fields['custom'].queryset, 42)
+
class FormFieldCallbackTests(TestCase):