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
|
qs = qs & other_qs
|
||||||
|
|
||||||
if self.opts.one_to_one_field:
|
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
|
return qs
|
||||||
|
|
||||||
|
|
|
@ -295,7 +295,7 @@ class Field(object):
|
||||||
return first_choice + list(self.choices)
|
return first_choice + list(self.choices)
|
||||||
rel_model = self.rel.to
|
rel_model = self.rel.to
|
||||||
return first_choice + [(x._get_pk_val(), str(x))
|
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):
|
def get_choices_default(self):
|
||||||
if self.radio_admin:
|
if self.radio_admin:
|
||||||
|
|
|
@ -679,7 +679,9 @@ class ManyToOneRel:
|
||||||
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
|
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.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.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.lookup_overrides = lookup_overrides or {}
|
||||||
self.raw_id_admin = raw_id_admin
|
self.raw_id_admin = raw_id_admin
|
||||||
self.multiple = True
|
self.multiple = True
|
||||||
|
@ -695,7 +697,9 @@ class OneToOneRel(ManyToOneRel):
|
||||||
self.to, self.field_name = to, field_name
|
self.to, self.field_name = to, field_name
|
||||||
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
|
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
|
||||||
self.related_name = related_name
|
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.lookup_overrides = lookup_overrides or {}
|
||||||
self.raw_id_admin = raw_id_admin
|
self.raw_id_admin = raw_id_admin
|
||||||
self.multiple = False
|
self.multiple = False
|
||||||
|
@ -707,7 +711,9 @@ class ManyToManyRel:
|
||||||
self.num_in_admin = num_in_admin
|
self.num_in_admin = num_in_admin
|
||||||
self.related_name = related_name
|
self.related_name = related_name
|
||||||
self.filter_interface = filter_interface
|
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.edit_inline = False
|
||||||
self.raw_id_admin = raw_id_admin
|
self.raw_id_admin = raw_id_admin
|
||||||
self.symmetrical = symmetrical
|
self.symmetrical = symmetrical
|
||||||
|
|
|
@ -68,6 +68,9 @@ class Manager(object):
|
||||||
def filter(self, *args, **kwargs):
|
def filter(self, *args, **kwargs):
|
||||||
return self.get_query_set().filter(*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):
|
def exclude(self, *args, **kwargs):
|
||||||
return self.get_query_set().exclude(*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.
|
# Sanity check -- Make sure the "parent" object exists.
|
||||||
# For example, make sure the Place exists for the Restaurant.
|
# For example, make sure the Place exists for the Restaurant.
|
||||||
# Let the ObjectDoesNotExist exception propagate up.
|
# Let the ObjectDoesNotExist exception propagate up.
|
||||||
lookup_kwargs = self.opts.one_to_one_field.rel.limit_choices_to
|
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
|
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)
|
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 = dict([(f.attname, f.get_default()) for f in self.opts.fields])
|
||||||
params[self.opts.pk.attname] = obj_key
|
params[self.opts.pk.attname] = obj_key
|
||||||
self.original_object = self.opts.get_model_module().Klass(**params)
|
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)
|
clone._filters = clone._filters & reduce(operator.and_, args)
|
||||||
return clone
|
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):
|
def select_related(self, true_or_false=True):
|
||||||
"Returns a new QuerySet instance with '_select_related' modified."
|
"Returns a new QuerySet instance with '_select_related' modified."
|
||||||
return self._clone(_select_related=true_or_false)
|
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
|
``pub_date`` before the current date/time to be
|
||||||
chosen.
|
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``.
|
Not compatible with ``edit_inline``.
|
||||||
|
|
||||||
``max_num_in_admin`` For inline-edited objects, this is the maximum
|
``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])
|
>>> Article.objects.filter(Q(headline__startswith='Hello')).in_bulk([1,2])
|
||||||
{1: Hello}
|
{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