diff --git a/django/db/models/query.py b/django/db/models/query.py index 2ff1c26344..c5e9cce90a 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -794,8 +794,9 @@ def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0, fields = row[index_start:index_end] if not [x for x in fields if x is not None]: # If we only have a list of Nones, there was not related object. - return None, index_end - obj = klass(*fields) + obj = None + else: + obj = klass(*fields) for f in klass._meta.fields: if not select_related_descend(f, restricted, requested): continue @@ -807,7 +808,8 @@ def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0, cur_depth+1, next) if cached_row: rel_obj, index_end = cached_row - setattr(obj, f.get_cache_name(), rel_obj) + if obj is not None: + setattr(obj, f.get_cache_name(), rel_obj) return obj, index_end diff --git a/tests/regressiontests/select_related_regress/models.py b/tests/regressiontests/select_related_regress/models.py index 163dc59164..eca620ccf7 100644 --- a/tests/regressiontests/select_related_regress/models.py +++ b/tests/regressiontests/select_related_regress/models.py @@ -49,6 +49,22 @@ class Enrollment(models.Model): std = models.ForeignKey(Student) cls = models.ForeignKey(Class) +# Models for testing bug #8036. +class Country(models.Model): + name = models.CharField(max_length=50) + +class State(models.Model): + name = models.CharField(max_length=50) + country = models.ForeignKey(Country) + +class ClientStatus(models.Model): + name = models.CharField(max_length=50) + +class Client(models.Model): + name = models.CharField(max_length=50) + state = models.ForeignKey(State, null=True) + status = models.ForeignKey(ClientStatus) + __test__ = {'API_TESTS': """ Regression test for bug #7110. When using select_related(), we must query the Device and Building tables using two different aliases (each) in order to @@ -100,4 +116,28 @@ separate). u"std" >>> e_related.cls.org.person.user.name u"org" + +Regression test for bug #8036: the first related model in the tests below +("state") is empty and we try to select the more remotely related +state__country. The regression here was not skipping the empty column results +for country before getting status. + +>>> australia = Country.objects.create(name='Australia') +>>> active = ClientStatus.objects.create(name='active') +>>> client = Client.objects.create(name='client', status=active) + +>>> client.status + +>>> Client.objects.select_related()[0].status + +>>> Client.objects.select_related('state')[0].status + +>>> Client.objects.select_related('state', 'status')[0].status + +>>> Client.objects.select_related('state__country')[0].status + +>>> Client.objects.select_related('state__country', 'status')[0].status + +>>> Client.objects.select_related('status')[0].status + """}