Fixed #1579 - added support for 'Q' objects in limit_choices_to.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@2850 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
3f932e31dc
commit
f57e34e990
|
@ -714,7 +714,7 @@ class ChangeList(object):
|
|||
qs = qs & other_qs
|
||||
|
||||
if self.opts.one_to_one_field:
|
||||
qs = qs.filter(**self.opts.one_to_one_field.rel.limit_choices_to)
|
||||
qs = qs.complex_filter(self.opts.one_to_one_field.rel.limit_choices_to)
|
||||
|
||||
return qs
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ class Field(object):
|
|||
return first_choice + list(self.choices)
|
||||
rel_model = self.rel.to
|
||||
return first_choice + [(x._get_pk_val(), str(x))
|
||||
for x in rel_model._default_manager.filter(**self.rel.limit_choices_to)]
|
||||
for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
|
||||
|
||||
def get_choices_default(self):
|
||||
if self.radio_admin:
|
||||
|
|
|
@ -679,7 +679,9 @@ class ManyToOneRel:
|
|||
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
|
||||
self.min_num_in_admin, self.max_num_in_admin = min_num_in_admin, max_num_in_admin
|
||||
self.num_extra_on_change, self.related_name = num_extra_on_change, related_name
|
||||
self.limit_choices_to = limit_choices_to or {}
|
||||
if limit_choices_to is None:
|
||||
limit_choices_to = {}
|
||||
self.limit_choices_to = limit_choices_to
|
||||
self.lookup_overrides = lookup_overrides or {}
|
||||
self.raw_id_admin = raw_id_admin
|
||||
self.multiple = True
|
||||
|
@ -695,7 +697,9 @@ class OneToOneRel(ManyToOneRel):
|
|||
self.to, self.field_name = to, field_name
|
||||
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
|
||||
self.related_name = related_name
|
||||
self.limit_choices_to = limit_choices_to or {}
|
||||
if limit_choices_to is None:
|
||||
limit_choices_to = {}
|
||||
self.limit_choices_to = limit_choices_to
|
||||
self.lookup_overrides = lookup_overrides or {}
|
||||
self.raw_id_admin = raw_id_admin
|
||||
self.multiple = False
|
||||
|
@ -707,7 +711,9 @@ class ManyToManyRel:
|
|||
self.num_in_admin = num_in_admin
|
||||
self.related_name = related_name
|
||||
self.filter_interface = filter_interface
|
||||
self.limit_choices_to = limit_choices_to or {}
|
||||
if limit_choices_to is None:
|
||||
limit_choices_to = {}
|
||||
self.limit_choices_to = limit_choices_to
|
||||
self.edit_inline = False
|
||||
self.raw_id_admin = raw_id_admin
|
||||
self.symmetrical = symmetrical
|
||||
|
|
|
@ -68,6 +68,9 @@ class Manager(object):
|
|||
def filter(self, *args, **kwargs):
|
||||
return self.get_query_set().filter(*args, **kwargs)
|
||||
|
||||
def complex_filter(self, *args, **kwargs):
|
||||
return self.get_query_set().complex_filter(*args, **kwargs)
|
||||
|
||||
def exclude(self, *args, **kwargs):
|
||||
return self.get_query_set().exclude(*args, **kwargs)
|
||||
|
||||
|
|
|
@ -261,9 +261,9 @@ class AutomaticChangeManipulator(AutomaticManipulator):
|
|||
# Sanity check -- Make sure the "parent" object exists.
|
||||
# For example, make sure the Place exists for the Restaurant.
|
||||
# Let the ObjectDoesNotExist exception propagate up.
|
||||
lookup_kwargs = self.opts.one_to_one_field.rel.limit_choices_to
|
||||
lookup_kwargs['%s__exact' % self.opts.one_to_one_field.rel.field_name] = obj_key
|
||||
self.opts.one_to_one_field.rel.to.get_model_module().get(**lookup_kwargs)
|
||||
limit_choices_to = self.opts.one_to_one_field.rel.limit_choices_to
|
||||
lookup_kwargs = {'%s__exact' % self.opts.one_to_one_field.rel.field_name: obj_key}
|
||||
self.opts.one_to_one_field.rel.to.get_model_module().complex_filter(limit_choices_to).get(**lookup_kwargs)
|
||||
params = dict([(f.attname, f.get_default()) for f in self.opts.fields])
|
||||
params[self.opts.pk.attname] = obj_key
|
||||
self.original_object = self.opts.get_model_module().Klass(**params)
|
||||
|
|
|
@ -297,6 +297,17 @@ class QuerySet(object):
|
|||
clone._filters = clone._filters & reduce(operator.and_, args)
|
||||
return clone
|
||||
|
||||
def complex_filter(self, filter_obj):
|
||||
"""Returns a new QuerySet instance with filter_obj added to the filters.
|
||||
filter_obj can be a Q object (has 'get_sql' method) or a dictionary of
|
||||
keyword lookup arguments."""
|
||||
# This exists to support framework features such as 'limit_choices_to',
|
||||
# and usually it will be more natural to use other methods.
|
||||
if hasattr(filter_obj, 'get_sql'):
|
||||
return self._filter_or_exclude(None, filter_obj)
|
||||
else:
|
||||
return self._filter_or_exclude(Q, **filter_obj)
|
||||
|
||||
def select_related(self, true_or_false=True):
|
||||
"Returns a new QuerySet instance with '_select_related' modified."
|
||||
return self._clone(_select_related=true_or_false)
|
||||
|
|
|
@ -704,6 +704,10 @@ relationship should work. All are optional:
|
|||
``pub_date`` before the current date/time to be
|
||||
chosen.
|
||||
|
||||
Instead of a dictionary this can also be a ``Q`` object
|
||||
(an object with a ``get_sql()`` method) for more complex
|
||||
queries.
|
||||
|
||||
Not compatible with ``edit_inline``.
|
||||
|
||||
``max_num_in_admin`` For inline-edited objects, this is the maximum
|
||||
|
|
|
@ -86,4 +86,11 @@ Hello and goodbye
|
|||
>>> Article.objects.filter(Q(headline__startswith='Hello')).in_bulk([1,2])
|
||||
{1: Hello}
|
||||
|
||||
# The 'complex_filter' method supports framework features such as
|
||||
# 'limit_choices_to' which normally take a single dictionary of lookup arguments
|
||||
# but need to support arbitrary queries via Q objects too.
|
||||
>>> Article.objects.complex_filter({'pk': 1})
|
||||
[Hello]
|
||||
>>> Article.objects.complex_filter(Q(pk=1) | Q(pk=2))
|
||||
[Hello, Goodbye]
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue