Ticket #14705: 14705_model_fields_order.diff

File 14705_model_fields_order.diff, 5.4 KB (added by julien, 4 years ago)
  • django/db/models/base.py

    diff --git a/django/db/models/base.py b/django/db/models/base.py
    index 4000379..3c4b65d 100644
    a b class ModelBase(type): 
    101101                     new_class._meta.virtual_fields
    102102        field_names = set([f.name for f in new_fields])
    103103
     104        # Things without _meta aren't functional models, so they're
     105        # uninteresting parents.
     106        parents = [p for p in parents if hasattr(p, '_meta')]
     107        new_class._meta.model_bases = parents
     108
    104109        # Basic setup for proxy models.
    105110        if is_proxy:
    106111            base = None
    107             for parent in [cls for cls in parents if hasattr(cls, '_meta')]:
     112            for parent in parents:
    108113                if parent._meta.abstract:
    109114                    if parent._meta.fields:
    110115                        raise TypeError("Abstract base class containing model fields not permitted for proxy model '%s'." % name)
    class ModelBase(type): 
    129134
    130135        for base in parents:
    131136            original_base = base
    132             if not hasattr(base, '_meta'):
    133                 # Things without _meta aren't functional models, so they're
    134                 # uninteresting parents.
    135                 continue
    136 
    137137            parent_fields = base._meta.local_fields + base._meta.local_many_to_many
    138138            # Check for clashes between locally declared fields and those
    139139            # on the base classes (we cannot handle shadowed fields at the
  • django/db/models/options.py

    diff --git a/django/db/models/options.py b/django/db/models/options.py
    index 2f64c56..052d158 100644
    a b class Options(object): 
    4747        self.proxy = False
    4848        self.proxy_for_model = None
    4949        self.parents = SortedDict()
     50        self.model_bases = []
    5051        self.duplicate_targets = {}
    5152        self.auto_created = False
    5253
    class Options(object): 
    232233
    233234    def _fill_fields_cache(self):
    234235        cache = []
    235         for parent in self.parents:
    236             for field, model in parent._meta.get_fields_with_model():
    237                 if model:
    238                     cache.append((field, model))
     236        local_fields = list(self.local_fields)
     237        for field in self.local_fields:
     238            if isinstance(field, AutoField):
     239                cache.append((field, None))
     240                local_fields.remove(field)
     241                break
     242        for base in self.model_bases:
     243            for field, model in base._meta.get_fields_with_model():
     244                if not model:
     245                    model = base
     246                if model._meta.abstract:
     247                    field_index = local_fields.index(field)
     248                    cache.append((local_fields[field_index], None))
     249                    del local_fields[field_index]
    239250                else:
    240                     cache.append((field, parent))
    241         cache.extend([(f, None) for f in self.local_fields])
     251                    cache.append((field, model))
     252            if base in self.parents:
     253                field = self.parents[base]
     254                if field:
     255                    cache.append((field, None))
     256                    local_fields.remove(field)
     257        cache.extend([(f, None) for f in local_fields])
    242258        self._field_cache = tuple(cache)
    243259        self._field_name_cache = [x for x, _ in cache]
    244260
  • tests/modeltests/model_inheritance/models.py

    diff --git a/tests/modeltests/model_inheritance/models.py b/tests/modeltests/model_inheritance/models.py
    index a0fed8a..1537b1e 100644
    a b class ParkingLot(Place): 
    119119    def __unicode__(self):
    120120        return u"%s the parking lot" % self.name
    121121
     122class AbstractModelOne(models.Model):
     123    field_one = models.BooleanField()
     124    field_two = models.TextField()
     125
     126    class Meta:
     127        abstract = True
     128
     129class AbstractModelTwo(models.Model):
     130    field_three = models.BooleanField()
     131    field_four = models.TextField()
     132
     133    class Meta:
     134        abstract = True
     135
     136class OneTwo(AbstractModelOne, AbstractModelTwo):
     137    pass
     138
     139class TwoOne(AbstractModelTwo, AbstractModelOne):
     140    pass
     141
    122142#
    123143# Abstract base classes with related models where the sub-class has the
    124144# same name in a different app and inherits from the same abstract base
  • tests/modeltests/model_inheritance/tests.py

    diff --git a/tests/modeltests/model_inheritance/tests.py b/tests/modeltests/model_inheritance/tests.py
    index 334297a..1078b1e 100644
    a b from django.core.exceptions import FieldError 
    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, Student, StudentWorker, Supplier, Worker, MixinModel,
     8    OneTwo, TwoOne)
    89
    910
    1011class ModelInheritanceTests(TestCase):
    class ModelInheritanceTests(TestCase): 
    269270        self.assertNumQueries(1,
    270271            lambda: ItalianRestaurant.objects.select_related("chef")[0].chef
    271272        )
     273       
     274        names = [field.name for field in OneTwo._meta.fields]
     275        self.assertEqual(["id", "field_one", "field_two", "field_three",
     276            "field_four"], names)
     277        names = [field.name for field in TwoOne._meta.fields]
     278        self.assertEqual(["id", "field_three", "field_four", "field_one",
     279                "field_two"], names)
    272280
    273281    def test_mixin_init(self):
    274282        m = MixinModel()
Back to Top