diff options
| author | Christopher Adams <christopher.r.adams@gmail.com> | 2014-02-01 14:23:31 -0500 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2014-02-11 14:05:12 -0500 |
| commit | eefc88feefec0c3685bfb102714530b751b4ae90 (patch) | |
| tree | 3cab4b02c13b76b6355d475d91ca2e157a126b18 /django/contrib/admin | |
| parent | a718fcf201b04ba254e9073be82f51ae1ae3a853 (diff) | |
Fixed #2445 -- Allowed limit_choices_to attribute to be a callable.
ForeignKey or ManyToManyField attribute ``limit_choices_to`` can now
be a callable that returns either a ``Q`` object or a dict.
Thanks michael at actrix.gen.nz for the original suggestion.
Diffstat (limited to 'django/contrib/admin')
| -rw-r--r-- | django/contrib/admin/options.py | 5 | ||||
| -rw-r--r-- | django/contrib/admin/utils.py | 12 | ||||
| -rw-r--r-- | django/contrib/admin/widgets.py | 5 |
3 files changed, 14 insertions, 8 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index e3c3e8e57e..7b0dd8ebcb 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -240,7 +240,7 @@ class BaseModelAdmin(six.with_metaclass(RenameBaseModelAdminMethods)): if related_admin is not None: ordering = related_admin.get_ordering(request) if ordering is not None and ordering != (): - return db_field.rel.to._default_manager.using(db).order_by(*ordering).complex_filter(db_field.rel.limit_choices_to) + return db_field.rel.to._default_manager.using(db).order_by(*ordering) return None def formfield_for_foreignkey(self, db_field, request=None, **kwargs): @@ -383,6 +383,9 @@ class BaseModelAdmin(six.with_metaclass(RenameBaseModelAdminMethods)): # ForeignKeyRawIdWidget, on the basis of ForeignKey.limit_choices_to, # are allowed to work. for l in model._meta.related_fkey_lookups: + # As ``limit_choices_to`` can be a callable, invoke it here. + if callable(l): + l = l() for k, v in widgets.url_params_from_lookup_dict(l).items(): if k == lookup and v == value: return True diff --git a/django/contrib/admin/utils.py b/django/contrib/admin/utils.py index 0b74a6e75f..a2f2e9fa7b 100644 --- a/django/contrib/admin/utils.py +++ b/django/contrib/admin/utils.py @@ -459,17 +459,17 @@ def get_limit_choices_to_from_path(model, path): """ Return Q object for limiting choices if applicable. If final model in path is linked via a ForeignKey or ManyToManyField which - has a `limit_choices_to` attribute, return it as a Q object. + has a ``limit_choices_to`` attribute, return it as a Q object. """ - fields = get_fields_from_path(model, path) fields = remove_trailing_data_field(fields) - limit_choices_to = ( + get_limit_choices_to = ( fields and hasattr(fields[-1], 'rel') and - getattr(fields[-1].rel, 'limit_choices_to', None)) - if not limit_choices_to: + getattr(fields[-1].rel, 'get_limit_choices_to', None)) + if not get_limit_choices_to: return models.Q() # empty Q - elif isinstance(limit_choices_to, models.Q): + limit_choices_to = get_limit_choices_to() + if isinstance(limit_choices_to, models.Q): return limit_choices_to # already a Q else: return models.Q(**limit_choices_to) # convert dict to Q diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py index f527d72f3f..f501ffb1a8 100644 --- a/django/contrib/admin/widgets.py +++ b/django/contrib/admin/widgets.py @@ -180,7 +180,10 @@ class ForeignKeyRawIdWidget(forms.TextInput): return mark_safe(''.join(output)) def base_url_parameters(self): - return url_params_from_lookup_dict(self.rel.limit_choices_to) + limit_choices_to = self.rel.limit_choices_to + if callable(limit_choices_to): + limit_choices_to = limit_choices_to() + return url_params_from_lookup_dict(limit_choices_to) def url_parameters(self): from django.contrib.admin.views.main import TO_FIELD_VAR |
