diff options
| author | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2008-08-26 20:44:20 +0000 |
|---|---|---|
| committer | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2008-08-26 20:44:20 +0000 |
| commit | 8f5234d801ebd2e8b526d4c75c94c89ea21eb440 (patch) | |
| tree | 936310bd01f6316783001358277352b5a3d9956b | |
| parent | 6056ab1beed04f53013ee83fc82303b5c42c9fbd (diff) | |
Fixed #8036 -- Fixed a case when attempting to traverse non-existent related
instances. We weren't skipping the correct output columns before processing
subsequent existing related instances. Thanks to mrmachine for the test case.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8598 bcc190cf-cafb-0310-a4f2-bffc1f526a37
| -rw-r--r-- | django/db/models/query.py | 8 | ||||
| -rw-r--r-- | tests/regressiontests/select_related_regress/models.py | 40 |
2 files changed, 45 insertions, 3 deletions
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 +<ClientStatus: ClientStatus object> +>>> Client.objects.select_related()[0].status +<ClientStatus: ClientStatus object> +>>> Client.objects.select_related('state')[0].status +<ClientStatus: ClientStatus object> +>>> Client.objects.select_related('state', 'status')[0].status +<ClientStatus: ClientStatus object> +>>> Client.objects.select_related('state__country')[0].status +<ClientStatus: ClientStatus object> +>>> Client.objects.select_related('state__country', 'status')[0].status +<ClientStatus: ClientStatus object> +>>> Client.objects.select_related('status')[0].status +<ClientStatus: ClientStatus object> """} |
