diff options
| author | Jon Dufresne <jon.dufresne@gmail.com> | 2017-06-28 20:30:19 -0700 |
|---|---|---|
| committer | Jon Dufresne <jon.dufresne@gmail.com> | 2017-06-30 15:57:48 -0700 |
| commit | a1be12fe193c8f3de8a0b0820f460a302472375f (patch) | |
| tree | c91fc4242a996489ede8e72aeb1a9f6ba91c5695 /django/forms/models.py | |
| parent | 5cbcb3683964205ce023157ca181d05a31be2ab5 (diff) | |
Fixed #28345 -- Applied limit_choices_to during ModelForm.__init__().
field_for_model() now has an additional keyword argument,
apply_limit_choices_to, allowing it to continue to be used to create
form fields dynamically after ModelForm.__init__() is called.
Thanks Tim Graham for the review.
Diffstat (limited to 'django/forms/models.py')
| -rw-r--r-- | django/forms/models.py | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/django/forms/models.py b/django/forms/models.py index 79e4452b17..bcb417489b 100644 --- a/django/forms/models.py +++ b/django/forms/models.py @@ -93,10 +93,18 @@ def model_to_dict(instance, fields=None, exclude=None): return data +def apply_limit_choices_to_to_formfield(formfield): + """Apply limit_choices_to to the formfield's queryset if needed.""" + 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: + formfield.queryset = formfield.queryset.complex_filter(limit_choices_to) + + def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield_callback=None, localized_fields=None, labels=None, help_texts=None, error_messages=None, - field_classes=None): + field_classes=None, *, apply_limit_choices_to=True): """ Return an ``OrderedDict`` containing form fields for the given model. @@ -123,6 +131,9 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None, ``field_classes`` is a dictionary of model field names mapped to a form field class. + + ``apply_limit_choices_to`` is a boolean indicating if limit_choices_to + should be applied to a field's queryset. """ field_list = [] ignored = [] @@ -166,11 +177,8 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None, formfield = formfield_callback(f, **kwargs) if formfield: - # Apply ``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: - formfield.queryset = formfield.queryset.complex_filter(limit_choices_to) + if apply_limit_choices_to: + apply_limit_choices_to_to_formfield(formfield) field_list.append((f.name, formfield)) else: ignored.append(f.name) @@ -241,11 +249,13 @@ class ModelFormMetaclass(DeclarativeFieldsMetaclass): # fields from the model" opts.fields = None - fields = fields_for_model(opts.model, opts.fields, opts.exclude, - opts.widgets, formfield_callback, - opts.localized_fields, opts.labels, - opts.help_texts, opts.error_messages, - opts.field_classes) + fields = fields_for_model( + opts.model, opts.fields, opts.exclude, opts.widgets, + formfield_callback, opts.localized_fields, opts.labels, + opts.help_texts, opts.error_messages, opts.field_classes, + # limit_choices_to will be applied during ModelForm.__init__(). + apply_limit_choices_to=False, + ) # make sure opts.fields doesn't specify an invalid field none_model_fields = [k for k, v in fields.items() if not v] @@ -291,6 +301,8 @@ class BaseModelForm(BaseForm): data, files, auto_id, prefix, object_data, error_class, label_suffix, empty_permitted, use_required_attribute=use_required_attribute, ) + for formfield in self.fields.values(): + apply_limit_choices_to_to_formfield(formfield) def _get_validation_exclusions(self): """ |
