Ticket #10808: 10808b-14404.diff
File 10808b-14404.diff, 6.0 KB (added by , 14 years ago) |
---|
-
django/db/models/base.py
300 300 # Now we're left with the unprocessed fields that *must* come from 301 301 # keywords, or default. 302 302 303 # In the case of diamond inheritance, where B and C inherit from A, and 304 # D inherits from B and C, D will have "redundant" copies of each of 305 # A's fields. As we iterate through all the fields, the second time we 306 # see a field we run the risk of reassigning it the default value, so 307 # if a field has already been seen in assigned_fields, we ignore it. 308 assigned_fields = set() 303 309 for field in fields_iter: 310 if field.attname in assigned_fields: 311 continue 304 312 is_related_object = False 305 313 # This slightly odd construct is so that we can access any 306 314 # data-descriptor object (DeferredAttribute) without triggering its … … 345 353 setattr(self, field.name, rel_obj) 346 354 else: 347 355 setattr(self, field.attname, val) 356 assigned_fields.add(field.attname) 348 357 349 358 if kwargs: 350 359 for prop in kwargs.keys(): -
django/forms/models.py
796 796 from django.db.models import ForeignKey 797 797 opts = model._meta 798 798 if fk_name: 799 fks_to_parent = [f for f in opts.fields if f.name == fk_name] 800 if len(fks_to_parent) == 1: 801 fk = fks_to_parent[0] 802 if not isinstance(fk, ForeignKey) or \ 803 (fk.rel.to != parent_model and 804 fk.rel.to not in parent_model._meta.get_parent_list()): 805 raise Exception("fk_name '%s' is not a ForeignKey to %s" % (fk_name, parent_model)) 806 elif len(fks_to_parent) == 0: 807 raise Exception("%s has no field named '%s'" % (model, fk_name)) 799 fk = opts.get_field(fk_name,many_to_many=False) 800 if not isinstance(fk, ForeignKey) or \ 801 (fk.rel.to != parent_model and 802 fk.rel.to not in parent_model._meta.get_parent_list()): 803 raise Exception("fk_name '%s' is not a ForeignKey to %s" % (fk_name, parent_model)) 808 804 else: 809 805 # Try to discover what the ForeignKey from model to parent_model is 810 806 fks_to_parent = [ -
tests/modeltests/model_inheritance/tests.py
2 2 3 3 from django.core.exceptions import FieldError 4 4 from django.test import TestCase 5 from django.forms.models import inlineformset_factory 5 6 6 7 from models import (Chef, CommonInfo, ItalianRestaurant, ParkingLot, Place, 7 Post, Restaurant, Student, StudentWorker, Supplier, Worker) 8 Post, Restaurant, Student, StudentWorker, Supplier, Worker, 9 FoodPlace, Bar, Pizzeria, PizzeriaBar, Owner) 8 10 9 11 10 12 class ModelInheritanceTests(TestCase): … … 269 271 self.assertNumQueries(1, 270 272 lambda: ItalianRestaurant.objects.select_related("chef")[0].chef 271 273 ) 274 275 # Test of diamond inheritance __init__. If B and C inherit from A, 276 # and D inherits from B and C, we should be able to use __init__ 277 # for D to properly set all the fields, regardless of the redundant 278 # copies of A's fields that D inherits from B and C. 279 280 p = PizzeriaBar(name="Mike's", pizza_bar_specific_field="Doodle") 281 self.assertEqual(p.name,"Mike's") 282 self.assertEqual(p.pizza_bar_specific_field,"Doodle") 283 284 # Note that patch 10808.diff fixes only one symptom, not 285 # the real problem. The real problem is that in case of diamond 286 # inheritance there are duplicate field definitions (the first 287 # 4 fields occur twice): 288 289 self.assertEqual( 290 [f.name for f in p._meta.fields], 291 'id name owner foodplace_ptr ' 292 'id name owner foodplace_ptr ' 293 'pizzeria_ptr bar_ptr pizza_bar_specific_field'.split()) 294 295 # Another symptom of this problem is: 296 # When the top-level model of your diamond structure contains a ForeignKey, 297 # then you get problems when trying to create inline formsets: 298 299 try: 300 f = inlineformset_factory(Owner,PizzeriaBar) 301 self.fail("expected Exception: <class '...PizzeriaBar'> " 302 "has more than 1 ForeignKey to <class '....Owner'>") 303 except Exception: 304 pass 305 306 # Patch 10808b*.diff won't fix the real problem, but makes it possible to 307 # work around to specify the fk_name explicitly. 308 309 f = inlineformset_factory(Owner,PizzeriaBar,fk_name='owner') 310 311 # Before patch 10808b*.diff, the following failed because 312 # inlineformset_factory() just couldn't imagine that a model can 313 # have two fields with the same name. 314 315 316 317 No newline at end of file -
tests/modeltests/model_inheritance/models.py
143 143 144 144 def __unicode__(self): 145 145 return self.content 146 147 # 148 # Diamond inheritance test 149 # 150 151 class Owner(models.Model): 152 name = models.CharField(max_length=255) 153 154 class FoodPlace(models.Model): 155 name = models.CharField(max_length=255) 156 owner = models.ForeignKey(Owner,blank=True,null=True) 157 158 class Bar(FoodPlace): 159 pass 160 161 class Pizzeria(FoodPlace): 162 pass 163 164 class PizzeriaBar(Bar, Pizzeria): 165 pizza_bar_specific_field = models.CharField(max_length=255)