Loading django/forms/fields.py +0 −11 Original line number Diff line number Diff line Loading @@ -181,17 +181,6 @@ class Field(six.with_metaclass(RenameFieldMethods, 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. Loading django/forms/models.py +13 −4 Original line number Diff line number Diff line Loading @@ -328,11 +328,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): Loading Loading @@ -1133,6 +1131,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 Loading docs/releases/1.7.2.txt +4 −0 Original line number Diff line number Diff line Loading @@ -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`). tests/model_forms/tests.py +19 −0 Original line number Diff line number Diff line Loading @@ -2377,6 +2377,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``. Loading Loading @@ -2407,6 +2418,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): Loading Loading
django/forms/fields.py +0 −11 Original line number Diff line number Diff line Loading @@ -181,17 +181,6 @@ class Field(six.with_metaclass(RenameFieldMethods, 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. Loading
django/forms/models.py +13 −4 Original line number Diff line number Diff line Loading @@ -328,11 +328,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): Loading Loading @@ -1133,6 +1131,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 Loading
docs/releases/1.7.2.txt +4 −0 Original line number Diff line number Diff line Loading @@ -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`).
tests/model_forms/tests.py +19 −0 Original line number Diff line number Diff line Loading @@ -2377,6 +2377,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``. Loading Loading @@ -2407,6 +2418,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): Loading