Ticket #15279: patch_r16324.diff
File patch_r16324.diff, 7.0 KB (added by , 13 years ago) |
---|
-
django/db/models/fields/__init__.py
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 9037265..5e1d51f 100644
a b class Field(object): 115 115 messages.update(getattr(c, 'default_error_messages', {})) 116 116 messages.update(error_messages or {}) 117 117 self.error_messages = messages 118 self._declared_on_class = None 119 self._first_concrete_class = None 118 120 119 121 def __cmp__(self, other): 120 122 # This is needed because bisect does not take a comparison function. … … class Field(object): 231 233 def contribute_to_class(self, cls, name): 232 234 self.set_attributes_from_name(name) 233 235 self.model = cls 236 if self._declared_on_class is None: 237 self._declared_on_class = cls 238 if self._first_concrete_class is None and not cls._meta.abstract: 239 self._first_concrete_class = cls 240 for f in cls._meta.local_fields + cls._meta.local_many_to_many: 241 if f.name == self.name: 242 if self._is_duplicate(f): 243 return 244 break 234 245 cls._meta.add_field(self) 235 246 if self.choices: 236 247 setattr(cls, 'get_%s_display' % self.name, curry(cls._get_FIELD_display, field=self)) 237 248 249 def _is_duplicate(self, other): 250 """ 251 Returns ``True`` if ``self`` is a duplicate of ``other`` and false otherwise. 252 253 Two fields are duplicates if they were declared on the same class 254 and if either neither field has been on a concrete class or one 255 field's first concrete class is a subclass of the other field's first 256 concrete class. 257 258 """ 259 ocon = other._first_concrete_class 260 scon = self._first_concrete_class 261 return other._declared_on_class == self._declared_on_class and ((ocon is None and scon is None) or issubclass(scon, ocon) or issubclass(ocon, scon)) 262 238 263 def get_attname(self): 239 264 return self.name 240 265 -
django/db/models/options.py
diff --git a/django/db/models/options.py b/django/db/models/options.py index 6f0f406..55072e6 100644
a b class Options(object): 233 233 234 234 def _fill_fields_cache(self): 235 235 cache = [] 236 checks = {} 236 237 for parent in self.parents: 237 238 for field, model in parent._meta.get_fields_with_model(): 238 239 if model: 239 240 cache.append((field, model)) 240 241 else: 241 242 cache.append((field, parent)) 242 cache.extend([(f, None) for f in self.local_fields]) 243 checks[field.name] = field 244 cache.extend([(f, None) for f in self.local_fields if f.name not in checks or not f._is_duplicate(checks[f.name])]) 243 245 self._field_cache = tuple(cache) 244 246 self._field_name_cache = [x for x, _ in cache] 245 247 … … class Options(object): 263 265 264 266 def _fill_m2m_cache(self): 265 267 cache = SortedDict() 268 checks = {} 266 269 for parent in self.parents: 267 270 for field, model in parent._meta.get_m2m_with_model(): 268 271 if model: 269 272 cache[field] = model 270 273 else: 271 274 cache[field] = parent 275 checks[field.name] = field 272 276 for field in self.local_many_to_many: 273 cache[field] = None 277 if field.name not in checks or not field._is_duplicate(checks[field.name]): 278 cache[field] = None 274 279 self._m2m_cache = cache 275 280 276 281 def get_field(self, name, many_to_many=True): -
tests/modeltests/model_inheritance/models.py
diff --git a/tests/modeltests/model_inheritance/models.py b/tests/modeltests/model_inheritance/models.py index a0fed8a..46cf8f6 100644
a b class StudentWorker(Student, Worker): 48 48 class Post(models.Model): 49 49 title = models.CharField(max_length=50) 50 50 51 class Tag(models.Model): 52 name = models.CharField(max_length=10) 53 51 54 class Attachment(models.Model): 52 55 post = models.ForeignKey(Post, related_name='attached_%(class)s_set') 53 56 content = models.TextField() 57 tags = models.ManyToManyField(Tag, related_name='tagged_%(class)s_set') 54 58 55 59 class Meta: 56 60 abstract = True … … class Comment(Attachment): 64 68 class Link(Attachment): 65 69 url = models.URLField() 66 70 71 class OrangeAttachment(Attachment): 72 class Meta: 73 abstract = True 74 75 class BananaAttachment(Attachment): 76 class Meta: 77 abstract = True 78 79 class BlueberryAttachment(Attachment): 80 class Meta: 81 abstract = True 82 67 83 # 68 84 # Multi-table inheritance 69 85 # -
tests/modeltests/model_inheritance/tests.py
diff --git a/tests/modeltests/model_inheritance/tests.py b/tests/modeltests/model_inheritance/tests.py index 334297a..5e61784 100644
a b from django.core.exceptions import FieldError 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, Student, StudentWorker, Supplier, Worker, MixinModel, 8 OrangeAttachment, BananaAttachment, BlueberryAttachment) 8 9 9 10 10 11 class ModelInheritanceTests(TestCase): … … class ModelInheritanceTests(TestCase): 69 70 StudentWorker.objects.get, pk__lt=sw2.pk + 100 70 71 ) 71 72 73 def test_multiple_abstract_inheritance(self): 74 # Define class here to avoid model validation errors while running tests. 75 def check_duplicates(cls): 76 field_names = [field.name for field in cls._meta.fields] 77 field_name_set = list(set(field_names)) 78 self.assertEqual(sorted(field_names), sorted(field_name_set)) 79 m2m_names = [field.name for field in cls._meta.many_to_many] 80 m2m_name_set = list(set(m2m_names)) 81 self.assertEqual(sorted(m2m_names), sorted(m2m_name_set)) 82 83 class SmoothieAttachment(OrangeAttachment, BananaAttachment): 84 class Meta: 85 app_label = 'model_inheritance' 86 87 check_duplicates(SmoothieAttachment) 88 89 class AbstractSmoothieAttachment(OrangeAttachment, BananaAttachment): 90 class Meta: 91 abstract = True 92 app_label = 'model_inheritance' 93 94 check_duplicates(AbstractSmoothieAttachment) 95 96 class BlueberrySmoothieAttachment(BlueberryAttachment, SmoothieAttachment): 97 class Meta: 98 app_label = 'model_inheritance' 99 100 check_duplicates(BlueberrySmoothieAttachment) 101 102 class SmoothieBlueberryAttachment(SmoothieAttachment, BlueberryAttachment): 103 class Meta: 104 app_label = 'model_inheritance' 105 106 check_duplicates(SmoothieBlueberryAttachment) 107 72 108 def test_multiple_table(self): 73 109 post = Post.objects.create(title="Lorem Ipsum") 74 110 # The Post model has distinct accessors for the Comment and Link models.