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')) +[] + """}