Ticket #15844: 15844.r16622.diff

File 15844.r16622.diff, 5.4 KB (added by Johannes Dollinger, 13 years ago)
  • django/db/models/fields/related.py

     
    171171        raise TypeError("Related Field has invalid lookup: %s" % lookup_type)
    172172
    173173    def _pk_trace(self, value, prep_func, lookup_type, **kwargs):
    174         # Value may be a primary key, or an object held in a relation.
    175         # If it is an object, then we need to get the primary key value for
    176         # that object. In certain conditions (especially one-to-one relations),
    177         # the primary key may itself be an object - so we need to keep drilling
    178         # down until we hit a value that can be used for a comparison.
    179         v = value
    180 
    181         # In the case of an FK to 'self', this check allows to_field to be used
    182         # for both forwards and reverse lookups across the FK. (For normal FKs,
    183         # it's only relevant for forward lookups).
    184         if isinstance(v, self.rel.to):
    185             field_name = getattr(self.rel, "field_name", None)
     174        rel_meta = self.rel.to._meta
     175        if isinstance(value, self.rel.to):
     176            rel_meta = self.rel.to._meta
     177            field_name = getattr(self.rel, "field_name", rel_meta.pk.name)
     178            field = rel_meta.get_field(field_name)
     179            value = getattr(value, field.attname)
     180        elif hasattr(value, '_meta'):
     181            # This is a probably a reverse lookup.
     182            field = value._meta.pk
     183            value = value.pk
    186184        else:
    187             field_name = None
    188         try:
    189             while True:
    190                 if field_name is None:
    191                     field_name = v._meta.pk.name
    192                 v = getattr(v, field_name)
    193                 field_name = None
    194         except AttributeError:
    195             pass
    196         except exceptions.ObjectDoesNotExist:
    197             v = None
    198 
    199         field = self
    200         while field.rel:
    201             if hasattr(field.rel, 'field_name'):
    202                 field = field.rel.to._meta.get_field(field.rel.field_name)
    203             else:
    204                 field = field.rel.to._meta.pk
    205 
     185            field = self
     186            while field.rel:
     187                if hasattr(field.rel, 'field_name'):
     188                    field = field.rel.to._meta.get_field(field.rel.field_name)
     189                else:
     190                    field = field.rel.to._meta.pk
     191           
    206192        if lookup_type in ('range', 'in'):
    207             v = [v]
    208         v = getattr(field, prep_func)(lookup_type, v, **kwargs)
    209         if isinstance(v, list):
    210             v = v[0]
    211         return v
     193            value = [value]
     194        value = getattr(field, prep_func)(lookup_type, value, **kwargs)
     195        if isinstance(value, list):
     196            value = value[0]
     197        return value
    212198
    213199    def related_query_name(self):
    214200        # This method defines the name that can be used to identify this
     
    461447                clear.alters_data = True
    462448
    463449        manager = RelatedManager()
    464         attname = rel_field.rel.get_related_field().name
    465         manager.core_filters = {'%s__%s' % (rel_field.name, attname):
    466                 getattr(instance, attname)}
     450        to_field = rel_field.rel.get_related_field()
     451        manager.core_filters = {'%s__%s' % (rel_field.name, to_field.name):
     452                getattr(instance, to_field.attname)}
    467453        manager.model = self.related.model
    468454
    469455        return manager
  • tests/modeltests/model_inheritance/tests.py

     
    44from django.test import TestCase
    55
    66from models import (Chef, CommonInfo, ItalianRestaurant, ParkingLot, Place,
    7     Post, Restaurant, Student, StudentWorker, Supplier, Worker, MixinModel)
     7    Post, Restaurant, Person, Student, StudentWorker, Supplier, Worker, MixinModel)
    88
    99
    1010class ModelInheritanceTests(TestCase):
     
    270270            lambda: ItalianRestaurant.objects.select_related("chef")[0].chef
    271271        )
    272272
     273    def test_pktrace(self):
     274        r = Restaurant.objects.create(
     275            name="Demon Dogs",
     276            address="944 W. Fullerton",
     277            serves_hot_dogs=True,
     278            serves_pizza=False,
     279            rating=2
     280        )
     281        p = Person.objects.create(
     282            name="John",
     283            favorite_restaurant=r
     284        )
     285
     286        self.assertNumQueries(1,
     287            lambda: list(Person.objects.filter(favorite_restaurant=r))
     288        )
     289        self.assertNumQueries(1,
     290            lambda: list(r.fans.all())
     291        )
     292
    273293    def test_mixin_init(self):
    274294        m = MixinModel()
    275295        self.assertEqual(m.other_attr, 1)
  • tests/modeltests/model_inheritance/models.py

     
    119119    def __unicode__(self):
    120120        return u"%s the parking lot" % self.name
    121121
     122
     123class Person(models.Model):
     124    name = models.CharField(max_length=50)
     125    favorite_restaurant = models.ForeignKey(Restaurant, related_name="fans")
     126
    122127#
    123128# Abstract base classes with related models where the sub-class has the
    124129# same name in a different app and inherits from the same abstract base
Back to Top