Allow for matches against unsaved objects in querysets (which will therefore
match nothing). This allows for some more straightforward code in the admin interface. Fixed #7488 (all the debugging there was done by Brian Rosner, who narrowed it down to the item in this patch). git-svn-id: http://code.djangoproject.com/svn/django/trunk@8061 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
3912403550
commit
a7b556ca04
|
@ -35,20 +35,30 @@ class WhereNode(tree.Node):
|
||||||
storing any reference to field objects). Otherwise, the 'data' is
|
storing any reference to field objects). Otherwise, the 'data' is
|
||||||
stored unchanged and can be anything with an 'as_sql()' method.
|
stored unchanged and can be anything with an 'as_sql()' method.
|
||||||
"""
|
"""
|
||||||
|
# Because of circular imports, we need to import this here.
|
||||||
|
from django.db.models.base import ObjectDoesNotExist
|
||||||
|
|
||||||
if not isinstance(data, (list, tuple)):
|
if not isinstance(data, (list, tuple)):
|
||||||
super(WhereNode, self).add(data, connector)
|
super(WhereNode, self).add(data, connector)
|
||||||
return
|
return
|
||||||
|
|
||||||
alias, col, field, lookup_type, value = data
|
alias, col, field, lookup_type, value = data
|
||||||
if field:
|
try:
|
||||||
params = field.get_db_prep_lookup(lookup_type, value)
|
if field:
|
||||||
db_type = field.db_type()
|
params = field.get_db_prep_lookup(lookup_type, value)
|
||||||
else:
|
db_type = field.db_type()
|
||||||
# This is possible when we add a comparison to NULL sometimes (we
|
else:
|
||||||
# don't really need to waste time looking up the associated field
|
# This is possible when we add a comparison to NULL sometimes
|
||||||
# object).
|
# (we don't really need to waste time looking up the associated
|
||||||
params = Field().get_db_prep_lookup(lookup_type, value)
|
# field object).
|
||||||
db_type = None
|
params = Field().get_db_prep_lookup(lookup_type, value)
|
||||||
|
db_type = None
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
# This can happen when trying to insert a reference to a null pk.
|
||||||
|
# We break out of the normal path and indicate there's nothing to
|
||||||
|
# match.
|
||||||
|
super(WhereNode, self).add(NothingNode(), connector)
|
||||||
|
return
|
||||||
if isinstance(value, datetime.datetime):
|
if isinstance(value, datetime.datetime):
|
||||||
annotation = datetime.datetime
|
annotation = datetime.datetime
|
||||||
else:
|
else:
|
||||||
|
@ -190,3 +200,14 @@ class EverythingNode(object):
|
||||||
|
|
||||||
def relabel_aliases(self, change_map, node=None):
|
def relabel_aliases(self, change_map, node=None):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
class NothingNode(object):
|
||||||
|
"""
|
||||||
|
A node that matches nothing.
|
||||||
|
"""
|
||||||
|
def as_sql(self, qn=None):
|
||||||
|
raise EmptyResultSet
|
||||||
|
|
||||||
|
def relabel_aliases(self, change_map, node=None):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
|
@ -43,12 +43,17 @@ class ParkingLot(Place):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"%s the parking lot" % self.name
|
return u"%s the parking lot" % self.name
|
||||||
|
|
||||||
|
class Supplier(models.Model):
|
||||||
|
restaurant = models.ForeignKey(Restaurant)
|
||||||
|
|
||||||
class Parent(models.Model):
|
class Parent(models.Model):
|
||||||
created = models.DateTimeField(default=datetime.datetime.now)
|
created = models.DateTimeField(default=datetime.datetime.now)
|
||||||
|
|
||||||
class Child(Parent):
|
class Child(Parent):
|
||||||
name = models.CharField(max_length=10)
|
name = models.CharField(max_length=10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
__test__ = {'API_TESTS':"""
|
__test__ = {'API_TESTS':"""
|
||||||
# Regression for #7350, #7202
|
# Regression for #7350, #7202
|
||||||
# Check that when you create a Parent object with a specific reference to an
|
# Check that when you create a Parent object with a specific reference to an
|
||||||
|
@ -172,4 +177,9 @@ True
|
||||||
>>> r.id == r.place_ptr_id
|
>>> r.id == r.place_ptr_id
|
||||||
True
|
True
|
||||||
|
|
||||||
|
# Regression test for #7488. This looks a little crazy, but it's the equivalent
|
||||||
|
# of what the admin interface has to do for the edit-inline case.
|
||||||
|
>>> Supplier.objects.filter(restaurant=Restaurant(name='xx', address='yy'))
|
||||||
|
[]
|
||||||
|
|
||||||
"""}
|
"""}
|
||||||
|
|
Loading…
Reference in New Issue