Loading django/db/models/fields/related.py +2 −0 Original line number Diff line number Diff line Loading @@ -496,6 +496,8 @@ class ForeignRelatedObjectsDescriptor(object): except (AttributeError, KeyError): db = self._db or router.db_for_read(self.model, instance=self.instance) qs = super(RelatedManager, self).get_query_set().using(db).filter(**self.core_filters) if getattr(self.instance, attname) is None: return qs.none() qs._known_related_objects = {rel_field: {self.instance.pk: self.instance}} return qs Loading tests/regressiontests/many_to_one_regress/models.py +6 −0 Original line number Diff line number Diff line Loading @@ -48,3 +48,9 @@ class Relation(models.Model): def __str__(self): return "%s - %s" % (self.left.category.name, self.right.category.name) class Car(models.Model): make = models.CharField(max_length=100, null=True, unique=True) class Driver(models.Model): car = models.ForeignKey(Car, to_field='make', null=True, related_name='drivers') tests/regressiontests/many_to_one_regress/tests.py +24 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,8 @@ from django.db import models from django.test import TestCase from django.utils import six from .models import First, Third, Parent, Child, Category, Record, Relation from .models import ( First, Third, Parent, Child, Category, Record, Relation, Car, Driver) class ManyToOneRegressionTests(TestCase): Loading Loading @@ -111,3 +112,25 @@ class ManyToOneRegressionTests(TestCase): # of a model, and interrogate its related field. cat = models.ForeignKey(Category) self.assertEqual('id', cat.rel.get_related_field().name) def test_relation_unsaved(self): # Test that the <field>_set manager does not join on Null value fields (#17541) Third.objects.create(name='Third 1') Third.objects.create(name='Third 2') th = Third(name="testing") # The object isn't saved an thus the relation field is null - we won't even # execute a query in this case. with self.assertNumQueries(0): self.assertEqual(th.child_set.count(), 0) th.save() # Now the model is saved, so we will need to execute an query. with self.assertNumQueries(1): self.assertEqual(th.child_set.count(), 0) def test_related_null_to_field(self): c1 = Car.objects.create() c2 = Car.objects.create() d1 = Driver.objects.create() self.assertIs(d1.car, None) with self.assertNumQueries(0): self.assertEqual(list(c1.drivers.all()), []) Loading
django/db/models/fields/related.py +2 −0 Original line number Diff line number Diff line Loading @@ -496,6 +496,8 @@ class ForeignRelatedObjectsDescriptor(object): except (AttributeError, KeyError): db = self._db or router.db_for_read(self.model, instance=self.instance) qs = super(RelatedManager, self).get_query_set().using(db).filter(**self.core_filters) if getattr(self.instance, attname) is None: return qs.none() qs._known_related_objects = {rel_field: {self.instance.pk: self.instance}} return qs Loading
tests/regressiontests/many_to_one_regress/models.py +6 −0 Original line number Diff line number Diff line Loading @@ -48,3 +48,9 @@ class Relation(models.Model): def __str__(self): return "%s - %s" % (self.left.category.name, self.right.category.name) class Car(models.Model): make = models.CharField(max_length=100, null=True, unique=True) class Driver(models.Model): car = models.ForeignKey(Car, to_field='make', null=True, related_name='drivers')
tests/regressiontests/many_to_one_regress/tests.py +24 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,8 @@ from django.db import models from django.test import TestCase from django.utils import six from .models import First, Third, Parent, Child, Category, Record, Relation from .models import ( First, Third, Parent, Child, Category, Record, Relation, Car, Driver) class ManyToOneRegressionTests(TestCase): Loading Loading @@ -111,3 +112,25 @@ class ManyToOneRegressionTests(TestCase): # of a model, and interrogate its related field. cat = models.ForeignKey(Category) self.assertEqual('id', cat.rel.get_related_field().name) def test_relation_unsaved(self): # Test that the <field>_set manager does not join on Null value fields (#17541) Third.objects.create(name='Third 1') Third.objects.create(name='Third 2') th = Third(name="testing") # The object isn't saved an thus the relation field is null - we won't even # execute a query in this case. with self.assertNumQueries(0): self.assertEqual(th.child_set.count(), 0) th.save() # Now the model is saved, so we will need to execute an query. with self.assertNumQueries(1): self.assertEqual(th.child_set.count(), 0) def test_related_null_to_field(self): c1 = Car.objects.create() c2 = Car.objects.create() d1 = Driver.objects.create() self.assertIs(d1.car, None) with self.assertNumQueries(0): self.assertEqual(list(c1.drivers.all()), [])