Ticket #15844: 15844.r16622.diff
File 15844.r16622.diff, 5.4 KB (added by , 13 years ago) |
---|
-
django/db/models/fields/related.py
171 171 raise TypeError("Related Field has invalid lookup: %s" % lookup_type) 172 172 173 173 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 186 184 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 206 192 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 212 198 213 199 def related_query_name(self): 214 200 # This method defines the name that can be used to identify this … … 461 447 clear.alters_data = True 462 448 463 449 manager = RelatedManager() 464 attname = rel_field.rel.get_related_field().name465 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)} 467 453 manager.model = self.related.model 468 454 469 455 return manager -
tests/modeltests/model_inheritance/tests.py
4 4 from django.test import TestCase 5 5 6 6 from models import (Chef, CommonInfo, ItalianRestaurant, ParkingLot, Place, 7 Post, Restaurant, Student, StudentWorker, Supplier, Worker, MixinModel)7 Post, Restaurant, Person, Student, StudentWorker, Supplier, Worker, MixinModel) 8 8 9 9 10 10 class ModelInheritanceTests(TestCase): … … 270 270 lambda: ItalianRestaurant.objects.select_related("chef")[0].chef 271 271 ) 272 272 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 273 293 def test_mixin_init(self): 274 294 m = MixinModel() 275 295 self.assertEqual(m.other_attr, 1) -
tests/modeltests/model_inheritance/models.py
119 119 def __unicode__(self): 120 120 return u"%s the parking lot" % self.name 121 121 122 123 class Person(models.Model): 124 name = models.CharField(max_length=50) 125 favorite_restaurant = models.ForeignKey(Restaurant, related_name="fans") 126 122 127 # 123 128 # Abstract base classes with related models where the sub-class has the 124 129 # same name in a different app and inherits from the same abstract base