summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2008-07-23 06:12:15 +0000
committerMalcolm Tredinnick <malcolm.tredinnick@gmail.com>2008-07-23 06:12:15 +0000
commita7b556ca044b2d51d25d566a7ce6410111cf50e1 (patch)
treec344b8708480f3eb3acddf1e799c0ce0a30ca42e
parent3912403550e31ddb3a002789dd2fe3379a4e006e (diff)
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
-rw-r--r--django/db/models/sql/where.py39
-rw-r--r--tests/regressiontests/model_inheritance_regress/models.py10
2 files changed, 40 insertions, 9 deletions
diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py
index 18e4bf2f7e..662d99a4a2 100644
--- a/django/db/models/sql/where.py
+++ b/django/db/models/sql/where.py
@@ -35,20 +35,30 @@ class WhereNode(tree.Node):
storing any reference to field objects). Otherwise, the 'data' is
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)):
super(WhereNode, self).add(data, connector)
return
alias, col, field, lookup_type, value = data
- if field:
- params = field.get_db_prep_lookup(lookup_type, value)
- db_type = field.db_type()
- else:
- # This is possible when we add a comparison to NULL sometimes (we
- # don't really need to waste time looking up the associated field
- # object).
- params = Field().get_db_prep_lookup(lookup_type, value)
- db_type = None
+ try:
+ if field:
+ params = field.get_db_prep_lookup(lookup_type, value)
+ db_type = field.db_type()
+ else:
+ # This is possible when we add a comparison to NULL sometimes
+ # (we don't really need to waste time looking up the associated
+ # field object).
+ 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):
annotation = datetime.datetime
else:
@@ -190,3 +200,14 @@ class EverythingNode(object):
def relabel_aliases(self, change_map, node=None):
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
+
diff --git a/tests/regressiontests/model_inheritance_regress/models.py b/tests/regressiontests/model_inheritance_regress/models.py
index 0a812cf5ed..fb1fd62798 100644
--- a/tests/regressiontests/model_inheritance_regress/models.py
+++ b/tests/regressiontests/model_inheritance_regress/models.py
@@ -43,12 +43,17 @@ class ParkingLot(Place):
def __unicode__(self):
return u"%s the parking lot" % self.name
+class Supplier(models.Model):
+ restaurant = models.ForeignKey(Restaurant)
+
class Parent(models.Model):
created = models.DateTimeField(default=datetime.datetime.now)
class Child(Parent):
name = models.CharField(max_length=10)
+
+
__test__ = {'API_TESTS':"""
# Regression for #7350, #7202
# 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
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'))
+[]
+
"""}