Commit 8f5234d8 authored by Malcolm Tredinnick's avatar Malcolm Tredinnick
Browse files

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
parent 6056ab1b
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -794,7 +794,8 @@ 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 = None
    else:
        obj = klass(*fields)
    for f in klass._meta.fields:
        if not select_related_descend(f, restricted, requested):
@@ -807,6 +808,7 @@ 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
            if obj is not None:
                setattr(obj, f.get_cache_name(), rel_obj)
    return obj, index_end

+40 −0
Original line number Diff line number Diff line
@@ -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>
"""}