~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to django/db/models/base.py

  • Committer: Package Import Robot
  • Author(s): Raphaël Hertzog
  • Date: 2014-09-17 14:15:11 UTC
  • mfrom: (1.3.17) (6.2.18 experimental)
  • Revision ID: package-import@ubuntu.com-20140917141511-icneokthe9ww5sk4
Tags: 1.7-2
* Release to unstable.
* Add a migrate-south sample script to help users apply their South
  migrations. Thanks to Brian May.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
import copy
4
4
import sys
5
5
from functools import update_wrapper
6
 
from django.utils.six.moves import zip
 
6
import warnings
7
7
 
8
 
import django.db.models.manager  # Imported to register signal handler.
 
8
from django.apps import apps
 
9
from django.apps.config import MODELS_MODULE_NAME
 
10
import django.db.models.manager  # NOQA: Imported to register signal handler.
9
11
from django.conf import settings
 
12
from django.core import checks
10
13
from django.core.exceptions import (ObjectDoesNotExist,
11
14
    MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS)
12
15
from django.db.models.fields import AutoField, FieldDoesNotExist
19
22
from django.db.models.deletion import Collector
20
23
from django.db.models.options import Options
21
24
from django.db.models import signals
22
 
from django.db.models.loading import register_models, get_model
23
 
from django.utils.translation import ugettext_lazy as _
 
25
from django.utils import six
 
26
from django.utils.deprecation import RemovedInDjango19Warning
 
27
from django.utils.encoding import force_str, force_text
24
28
from django.utils.functional import curry
25
 
from django.utils.encoding import force_str, force_text
26
 
from django.utils import six
 
29
from django.utils.six.moves import zip
27
30
from django.utils.text import get_text_list, capfirst
 
31
from django.utils.translation import ugettext_lazy as _
28
32
 
29
33
 
30
34
def subclass_exception(name, parents, module, attached_to=None):
58
62
    def __new__(cls, name, bases, attrs):
59
63
        super_new = super(ModelBase, cls).__new__
60
64
 
61
 
        # six.with_metaclass() inserts an extra class called 'NewBase' in the
62
 
        # inheritance tree: Model -> NewBase -> object. But the initialization
63
 
        # should be executed only once for a given model class.
64
 
 
65
 
        # attrs will never be empty for classes declared in the standard way
66
 
        # (ie. with the `class` keyword). This is quite robust.
67
 
        if name == 'NewBase' and attrs == {}:
68
 
            return super_new(cls, name, bases, attrs)
69
 
 
70
65
        # Also ensure initialization is only performed for subclasses of Model
71
66
        # (excluding Model class itself).
72
 
        parents = [b for b in bases if isinstance(b, ModelBase) and
73
 
                not (b.__name__ == 'NewBase' and b.__mro__ == (b, object))]
 
67
        parents = [b for b in bases if isinstance(b, ModelBase)]
74
68
        if not parents:
75
69
            return super_new(cls, name, bases, attrs)
76
70
 
85
79
            meta = attr_meta
86
80
        base_meta = getattr(new_class, '_meta', None)
87
81
 
 
82
        # Look for an application configuration to attach the model to.
 
83
        app_config = apps.get_containing_app_config(module)
 
84
 
88
85
        if getattr(meta, 'app_label', None) is None:
89
 
            # Figure out the app_label by looking one level up.
90
 
            # For 'django.contrib.sites.models', this would be 'sites'.
91
 
            model_module = sys.modules[new_class.__module__]
92
 
            kwargs = {"app_label": model_module.__name__.split('.')[-2]}
 
86
 
 
87
            if app_config is None:
 
88
                # If the model is imported before the configuration for its
 
89
                # application is created (#21719), or isn't in an installed
 
90
                # application (#21680), use the legacy logic to figure out the
 
91
                # app_label by looking one level up from the package or module
 
92
                # named 'models'. If no such package or module exists, fall
 
93
                # back to looking one level up from the module this model is
 
94
                # defined in.
 
95
 
 
96
                # For 'django.contrib.sites.models', this would be 'sites'.
 
97
                # For 'geo.models.places' this would be 'geo'.
 
98
 
 
99
                msg = (
 
100
                    "Model class %s.%s doesn't declare an explicit app_label "
 
101
                    "and either isn't in an application in INSTALLED_APPS or "
 
102
                    "else was imported before its application was loaded. " %
 
103
                    (module, name))
 
104
                if abstract:
 
105
                    msg += "Its app_label will be set to None in Django 1.9."
 
106
                else:
 
107
                    msg += "This will no longer be supported in Django 1.9."
 
108
                warnings.warn(msg, RemovedInDjango19Warning, stacklevel=2)
 
109
 
 
110
                model_module = sys.modules[new_class.__module__]
 
111
                package_components = model_module.__name__.split('.')
 
112
                package_components.reverse()  # find the last occurrence of 'models'
 
113
                try:
 
114
                    app_label_index = package_components.index(MODELS_MODULE_NAME) + 1
 
115
                except ValueError:
 
116
                    app_label_index = 1
 
117
                kwargs = {"app_label": package_components[app_label_index]}
 
118
 
 
119
            else:
 
120
                kwargs = {"app_label": app_config.label}
 
121
 
93
122
        else:
94
123
            kwargs = {}
95
124
 
96
125
        new_class.add_to_class('_meta', Options(meta, **kwargs))
97
126
        if not abstract:
98
 
            new_class.add_to_class('DoesNotExist', subclass_exception(str('DoesNotExist'),
99
 
                    tuple(x.DoesNotExist
100
 
                          for x in parents if hasattr(x, '_meta') and not x._meta.abstract)
101
 
                    or (ObjectDoesNotExist,),
102
 
                    module, attached_to=new_class))
103
 
            new_class.add_to_class('MultipleObjectsReturned', subclass_exception(str('MultipleObjectsReturned'),
104
 
                    tuple(x.MultipleObjectsReturned
105
 
                          for x in parents if hasattr(x, '_meta') and not x._meta.abstract)
106
 
                    or (MultipleObjectsReturned,),
107
 
                    module, attached_to=new_class))
 
127
            new_class.add_to_class(
 
128
                'DoesNotExist',
 
129
                subclass_exception(
 
130
                    str('DoesNotExist'),
 
131
                    tuple(x.DoesNotExist for x in parents if hasattr(x, '_meta') and not x._meta.abstract) or (ObjectDoesNotExist,),
 
132
                    module,
 
133
                    attached_to=new_class))
 
134
            new_class.add_to_class(
 
135
                'MultipleObjectsReturned',
 
136
                subclass_exception(
 
137
                    str('MultipleObjectsReturned'),
 
138
                    tuple(x.MultipleObjectsReturned for x in parents if hasattr(x, '_meta') and not x._meta.abstract) or (MultipleObjectsReturned,),
 
139
                    module,
 
140
                    attached_to=new_class))
108
141
            if base_meta and not base_meta.abstract:
109
142
                # Non-abstract child classes inherit some attributes from their
110
143
                # non-abstract parent (unless an ABC comes before it in the
133
166
                new_class._default_manager = new_class._default_manager._copy_to_model(new_class)
134
167
                new_class._base_manager = new_class._base_manager._copy_to_model(new_class)
135
168
 
136
 
        # Bail out early if we have already created this class.
137
 
        m = get_model(new_class._meta.app_label, name,
138
 
                      seed_cache=False, only_installed=False)
139
 
        if m is not None:
140
 
            return m
141
 
 
142
169
        # Add all attributes to the class.
143
170
        for obj_name, obj in attrs.items():
144
171
            new_class.add_to_class(obj_name, obj)
145
172
 
146
173
        # All the fields of any type declared on this model
147
 
        new_fields = new_class._meta.local_fields + \
148
 
                     new_class._meta.local_many_to_many + \
149
 
                     new_class._meta.virtual_fields
150
 
        field_names = set([f.name for f in new_fields])
 
174
        new_fields = (
 
175
            new_class._meta.local_fields +
 
176
            new_class._meta.local_many_to_many +
 
177
            new_class._meta.virtual_fields
 
178
        )
 
179
        field_names = set(f.name for f in new_fields)
151
180
 
152
181
        # Basic setup for proxy models.
153
182
        if is_proxy:
154
183
            base = None
155
 
            for parent in [cls for cls in parents if hasattr(cls, '_meta')]:
 
184
            for parent in [kls for kls in parents if hasattr(kls, '_meta')]:
156
185
                if parent._meta.abstract:
157
186
                    if parent._meta.fields:
158
187
                        raise TypeError("Abstract base class containing model fields not permitted for proxy model '%s'." % name)
164
193
                    base = parent
165
194
            if base is None:
166
195
                raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
167
 
            if (new_class._meta.local_fields or
168
 
                    new_class._meta.local_many_to_many):
169
 
                raise FieldError("Proxy model '%s' contains model fields." % name)
170
196
            new_class._meta.setup_proxy(base)
171
197
            new_class._meta.concrete_model = base._meta.concrete_model
172
198
        else:
173
199
            new_class._meta.concrete_model = new_class
174
200
 
 
201
        # Collect the parent links for multi-table inheritance.
 
202
        parent_links = {}
 
203
        for base in reversed([new_class] + parents):
 
204
            # Conceptually equivalent to `if base is Model`.
 
205
            if not hasattr(base, '_meta'):
 
206
                continue
 
207
            # Skip concrete parent classes.
 
208
            if base != new_class and not base._meta.abstract:
 
209
                continue
 
210
            # Locate OneToOneField instances.
 
211
            for field in base._meta.local_fields:
 
212
                if isinstance(field, OneToOneField):
 
213
                    parent_links[field.rel.to] = field
 
214
 
175
215
        # Do the appropriate setup for any model parents.
176
 
        o2o_map = dict([(f.rel.to, f) for f in new_class._meta.local_fields
177
 
                if isinstance(f, OneToOneField)])
178
 
 
179
216
        for base in parents:
180
217
            original_base = base
181
218
            if not hasattr(base, '_meta'):
189
226
            # moment).
190
227
            for field in parent_fields:
191
228
                if field.name in field_names:
192
 
                    raise FieldError('Local field %r in class %r clashes '
193
 
                                     'with field of similar name from '
194
 
                                     'base class %r' %
195
 
                                        (field.name, name, base.__name__))
 
229
                    raise FieldError(
 
230
                        'Local field %r in class %r clashes '
 
231
                        'with field of similar name from '
 
232
                        'base class %r' % (field.name, name, base.__name__)
 
233
                    )
196
234
            if not base._meta.abstract:
197
235
                # Concrete classes...
198
236
                base = base._meta.concrete_model
199
 
                if base in o2o_map:
200
 
                    field = o2o_map[base]
 
237
                if base in parent_links:
 
238
                    field = parent_links[base]
201
239
                elif not is_proxy:
202
240
                    attr_name = '%s_ptr' % base._meta.model_name
203
241
                    field = OneToOneField(base, name=attr_name,
204
242
                            auto_created=True, parent_link=True)
205
 
                    new_class.add_to_class(attr_name, field)
 
243
                    # Only add the ptr field if it's not already present;
 
244
                    # e.g. migrations will already have it specified
 
245
                    if not hasattr(new_class, attr_name):
 
246
                        new_class.add_to_class(attr_name, field)
206
247
                else:
207
248
                    field = None
208
249
                new_class._meta.parents[base] = field
226
267
            # class
227
268
            for field in base._meta.virtual_fields:
228
269
                if base._meta.abstract and field.name in field_names:
229
 
                    raise FieldError('Local field %r in class %r clashes '\
230
 
                                     'with field of similar name from '\
231
 
                                     'abstract base class %r' % \
232
 
                                        (field.name, name, base.__name__))
 
270
                    raise FieldError(
 
271
                        'Local field %r in class %r clashes '
 
272
                        'with field of similar name from '
 
273
                        'abstract base class %r' % (field.name, name, base.__name__)
 
274
                    )
233
275
                new_class.add_to_class(field.name, copy.deepcopy(field))
234
276
 
235
277
        if abstract:
241
283
            return new_class
242
284
 
243
285
        new_class._prepare()
244
 
        register_models(new_class._meta.app_label, new_class)
245
 
 
246
 
        # Because of the way imports happen (recursively), we may or may not be
247
 
        # the first time this model tries to register with the framework. There
248
 
        # should only be one class for each model, so we always return the
249
 
        # registered version.
250
 
        return get_model(new_class._meta.app_label, name,
251
 
                         seed_cache=False, only_installed=False)
 
286
        new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
 
287
        return new_class
252
288
 
253
289
    def copy_managers(cls, base_managers):
254
290
        # This is in-place sorting of an Options attribute, but that's fine.
255
291
        base_managers.sort()
256
 
        for _, mgr_name, manager in base_managers:
 
292
        for _, mgr_name, manager in base_managers:  # NOQA (redefinition of _)
257
293
            val = getattr(cls, mgr_name, None)
258
294
            if not val or val is manager:
259
295
                new_manager = manager._copy_to_model(cls)
298
334
 
299
335
        # Give the class a docstring -- its definition.
300
336
        if cls.__doc__ is None:
301
 
            cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join([f.attname for f in opts.fields]))
 
337
            cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join(f.attname for f in opts.fields))
302
338
 
303
339
        if hasattr(cls, 'get_absolute_url'):
304
340
            cls.get_absolute_url = update_wrapper(curry(get_absolute_url, opts, cls.get_absolute_url),
431
467
        return '%s object' % self.__class__.__name__
432
468
 
433
469
    def __eq__(self, other):
434
 
        return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
 
470
        if not isinstance(other, Model):
 
471
            return False
 
472
        if self._meta.concrete_model != other._meta.concrete_model:
 
473
            return False
 
474
        my_pk = self._get_pk_val()
 
475
        if my_pk is None:
 
476
            return self is other
 
477
        return my_pk == other._get_pk_val()
435
478
 
436
479
    def __ne__(self, other):
437
480
        return not self.__eq__(other)
438
481
 
439
482
    def __hash__(self):
 
483
        if self._get_pk_val() is None:
 
484
            raise TypeError("Model instances without primary key value are unhashable")
440
485
        return hash(self._get_pk_val())
441
486
 
442
487
    def __reduce__(self):
533
578
                    field_names.add(field.attname)
534
579
            deferred_fields = [
535
580
                f.attname for f in self._meta.fields
536
 
                if f.attname not in self.__dict__
537
 
                   and isinstance(self.__class__.__dict__[f.attname],
538
 
                                  DeferredAttribute)]
 
581
                if (f.attname not in self.__dict__ and
 
582
                    isinstance(self.__class__.__dict__[f.attname], DeferredAttribute))
 
583
            ]
539
584
 
540
585
            loaded_fields = field_names.difference(deferred_fields)
541
586
            if loaded_fields:
884
929
                )
885
930
        return errors
886
931
 
887
 
    def date_error_message(self, lookup_type, field, unique_for):
 
932
    def date_error_message(self, lookup_type, field_name, unique_for):
888
933
        opts = self._meta
889
 
        return _("%(field_name)s must be unique for %(date_field)s %(lookup)s.") % {
890
 
            'field_name': six.text_type(capfirst(opts.get_field(field).verbose_name)),
891
 
            'date_field': six.text_type(capfirst(opts.get_field(unique_for).verbose_name)),
892
 
            'lookup': lookup_type,
893
 
        }
 
934
        field = opts.get_field(field_name)
 
935
        return ValidationError(
 
936
            message=field.error_messages['unique_for_date'],
 
937
            code='unique_for_date',
 
938
            params={
 
939
                'model': self,
 
940
                'model_name': six.text_type(capfirst(opts.verbose_name)),
 
941
                'lookup_type': lookup_type,
 
942
                'field': field_name,
 
943
                'field_label': six.text_type(capfirst(field.verbose_name)),
 
944
                'date_field': unique_for,
 
945
                'date_field_label': six.text_type(capfirst(opts.get_field(unique_for).verbose_name)),
 
946
            }
 
947
        )
894
948
 
895
949
    def unique_error_message(self, model_class, unique_check):
896
950
        opts = model_class._meta
897
 
        model_name = capfirst(opts.verbose_name)
 
951
 
 
952
        params = {
 
953
            'model': self,
 
954
            'model_class': model_class,
 
955
            'model_name': six.text_type(capfirst(opts.verbose_name)),
 
956
            'unique_check': unique_check,
 
957
        }
898
958
 
899
959
        # A unique field
900
960
        if len(unique_check) == 1:
901
 
            field_name = unique_check[0]
902
 
            field = opts.get_field(field_name)
903
 
            field_label = capfirst(field.verbose_name)
904
 
            # Insert the error into the error dict, very sneaky
905
 
            return field.error_messages['unique'] % {
906
 
                'model_name': six.text_type(model_name),
907
 
                'field_label': six.text_type(field_label)
908
 
            }
 
961
            field = opts.get_field(unique_check[0])
 
962
            params['field_label'] = six.text_type(capfirst(field.verbose_name))
 
963
            return ValidationError(
 
964
                message=field.error_messages['unique'],
 
965
                code='unique',
 
966
                params=params,
 
967
            )
 
968
 
909
969
        # unique_together
910
970
        else:
911
971
            field_labels = [capfirst(opts.get_field(f).verbose_name) for f in unique_check]
912
 
            field_labels = get_text_list(field_labels, _('and'))
913
 
            return _("%(model_name)s with this %(field_label)s already exists.") % {
914
 
                'model_name': six.text_type(model_name),
915
 
                'field_label': six.text_type(field_labels)
916
 
            }
 
972
            params['field_labels'] = six.text_type(get_text_list(field_labels, _('and')))
 
973
            return ValidationError(
 
974
                message=_("%(model_name)s with this %(field_labels)s already exists."),
 
975
                code='unique_together',
 
976
                params=params,
 
977
            )
917
978
 
918
979
    def full_clean(self, exclude=None, validate_unique=True):
919
980
        """
923
984
        errors = {}
924
985
        if exclude is None:
925
986
            exclude = []
 
987
        else:
 
988
            exclude = list(exclude)
926
989
 
927
990
        try:
928
991
            self.clean_fields(exclude=exclude)
951
1014
 
952
1015
    def clean_fields(self, exclude=None):
953
1016
        """
954
 
        Cleans all fields and raises a ValidationError containing message_dict
 
1017
        Cleans all fields and raises a ValidationError containing a dict
955
1018
        of all validation errors if any occur.
956
1019
        """
957
1020
        if exclude is None:
974
1037
        if errors:
975
1038
            raise ValidationError(errors)
976
1039
 
 
1040
    @classmethod
 
1041
    def check(cls, **kwargs):
 
1042
        errors = []
 
1043
        errors.extend(cls._check_swappable())
 
1044
        errors.extend(cls._check_model())
 
1045
        errors.extend(cls._check_managers(**kwargs))
 
1046
        if not cls._meta.swapped:
 
1047
            errors.extend(cls._check_fields(**kwargs))
 
1048
            errors.extend(cls._check_m2m_through_same_relationship())
 
1049
            clash_errors = cls._check_id_field() + cls._check_field_name_clashes()
 
1050
            errors.extend(clash_errors)
 
1051
            # If there are field name clashes, hide consequent column name
 
1052
            # clashes.
 
1053
            if not clash_errors:
 
1054
                errors.extend(cls._check_column_name_clashes())
 
1055
            errors.extend(cls._check_index_together())
 
1056
            errors.extend(cls._check_unique_together())
 
1057
            errors.extend(cls._check_ordering())
 
1058
 
 
1059
        return errors
 
1060
 
 
1061
    @classmethod
 
1062
    def _check_swappable(cls):
 
1063
        """ Check if the swapped model exists. """
 
1064
 
 
1065
        errors = []
 
1066
        if cls._meta.swapped:
 
1067
            try:
 
1068
                apps.get_model(cls._meta.swapped)
 
1069
            except ValueError:
 
1070
                errors.append(
 
1071
                    checks.Error(
 
1072
                        "'%s' is not of the form 'app_label.app_name'." % cls._meta.swappable,
 
1073
                        hint=None,
 
1074
                        obj=None,
 
1075
                        id='models.E001',
 
1076
                    )
 
1077
                )
 
1078
            except LookupError:
 
1079
                app_label, model_name = cls._meta.swapped.split('.')
 
1080
                errors.append(
 
1081
                    checks.Error(
 
1082
                        ("'%s' references '%s.%s', which has not been installed, or is abstract.") % (
 
1083
                            cls._meta.swappable, app_label, model_name
 
1084
                        ),
 
1085
                        hint=None,
 
1086
                        obj=None,
 
1087
                        id='models.E002',
 
1088
                    )
 
1089
                )
 
1090
        return errors
 
1091
 
 
1092
    @classmethod
 
1093
    def _check_model(cls):
 
1094
        errors = []
 
1095
        if cls._meta.proxy:
 
1096
            if cls._meta.local_fields or cls._meta.local_many_to_many:
 
1097
                errors.append(
 
1098
                    checks.Error(
 
1099
                        "Proxy model '%s' contains model fields." % cls.__name__,
 
1100
                        hint=None,
 
1101
                        obj=None,
 
1102
                        id='models.E017',
 
1103
                    )
 
1104
                )
 
1105
        return errors
 
1106
 
 
1107
    @classmethod
 
1108
    def _check_managers(cls, **kwargs):
 
1109
        """ Perform all manager checks. """
 
1110
 
 
1111
        errors = []
 
1112
        managers = cls._meta.concrete_managers + cls._meta.abstract_managers
 
1113
        for __, __, manager in managers:
 
1114
            errors.extend(manager.check(**kwargs))
 
1115
        return errors
 
1116
 
 
1117
    @classmethod
 
1118
    def _check_fields(cls, **kwargs):
 
1119
        """ Perform all field checks. """
 
1120
 
 
1121
        errors = []
 
1122
        for field in cls._meta.local_fields:
 
1123
            errors.extend(field.check(**kwargs))
 
1124
        for field in cls._meta.local_many_to_many:
 
1125
            errors.extend(field.check(from_model=cls, **kwargs))
 
1126
        return errors
 
1127
 
 
1128
    @classmethod
 
1129
    def _check_m2m_through_same_relationship(cls):
 
1130
        """ Check if no relationship model is used by more than one m2m field.
 
1131
        """
 
1132
 
 
1133
        errors = []
 
1134
        seen_intermediary_signatures = []
 
1135
 
 
1136
        fields = cls._meta.local_many_to_many
 
1137
 
 
1138
        # Skip when the target model wasn't found.
 
1139
        fields = (f for f in fields if isinstance(f.rel.to, ModelBase))
 
1140
 
 
1141
        # Skip when the relationship model wasn't found.
 
1142
        fields = (f for f in fields if isinstance(f.rel.through, ModelBase))
 
1143
 
 
1144
        for f in fields:
 
1145
            signature = (f.rel.to, cls, f.rel.through)
 
1146
            if signature in seen_intermediary_signatures:
 
1147
                errors.append(
 
1148
                    checks.Error(
 
1149
                        ("The model has two many-to-many relations through "
 
1150
                         "the intermediate model '%s.%s'.") % (
 
1151
                            f.rel.through._meta.app_label,
 
1152
                            f.rel.through._meta.object_name
 
1153
                        ),
 
1154
                        hint=None,
 
1155
                        obj=cls,
 
1156
                        id='models.E003',
 
1157
                    )
 
1158
                )
 
1159
            else:
 
1160
                seen_intermediary_signatures.append(signature)
 
1161
        return errors
 
1162
 
 
1163
    @classmethod
 
1164
    def _check_id_field(cls):
 
1165
        """ Check if `id` field is a primary key. """
 
1166
 
 
1167
        fields = list(f for f in cls._meta.local_fields
 
1168
            if f.name == 'id' and f != cls._meta.pk)
 
1169
        # fields is empty or consists of the invalid "id" field
 
1170
        if fields and not fields[0].primary_key and cls._meta.pk.name == 'id':
 
1171
            return [
 
1172
                checks.Error(
 
1173
                    ("'id' can only be used as a field name if the field also "
 
1174
                     "sets 'primary_key=True'."),
 
1175
                    hint=None,
 
1176
                    obj=cls,
 
1177
                    id='models.E004',
 
1178
                )
 
1179
            ]
 
1180
        else:
 
1181
            return []
 
1182
 
 
1183
    @classmethod
 
1184
    def _check_field_name_clashes(cls):
 
1185
        """ Ref #17673. """
 
1186
 
 
1187
        errors = []
 
1188
        used_fields = {}  # name or attname -> field
 
1189
 
 
1190
        # Check that multi-inheritance doesn't cause field name shadowing.
 
1191
        for parent in cls._meta.parents:
 
1192
            for f in parent._meta.local_fields:
 
1193
                clash = used_fields.get(f.name) or used_fields.get(f.attname) or None
 
1194
                if clash:
 
1195
                    errors.append(
 
1196
                        checks.Error(
 
1197
                            ("The field '%s' from parent model "
 
1198
                             "'%s' clashes with the field '%s' "
 
1199
                             "from parent model '%s'.") % (
 
1200
                                clash.name, clash.model._meta,
 
1201
                                f.name, f.model._meta
 
1202
                            ),
 
1203
                            hint=None,
 
1204
                            obj=cls,
 
1205
                            id='models.E005',
 
1206
                        )
 
1207
                    )
 
1208
                used_fields[f.name] = f
 
1209
                used_fields[f.attname] = f
 
1210
 
 
1211
        # Check that fields defined in the model don't clash with fields from
 
1212
        # parents.
 
1213
        for f in cls._meta.local_fields:
 
1214
            clash = used_fields.get(f.name) or used_fields.get(f.attname) or None
 
1215
            # Note that we may detect clash between user-defined non-unique
 
1216
            # field "id" and automatically added unique field "id", both
 
1217
            # defined at the same model. This special case is considered in
 
1218
            # _check_id_field and here we ignore it.
 
1219
            id_conflict = (f.name == "id" and
 
1220
                clash and clash.name == "id" and clash.model == cls)
 
1221
            if clash and not id_conflict:
 
1222
                errors.append(
 
1223
                    checks.Error(
 
1224
                        ("The field '%s' clashes with the field '%s' "
 
1225
                         "from model '%s'.") % (
 
1226
                            f.name, clash.name, clash.model._meta
 
1227
                        ),
 
1228
                        hint=None,
 
1229
                        obj=f,
 
1230
                        id='models.E006',
 
1231
                    )
 
1232
                )
 
1233
            used_fields[f.name] = f
 
1234
            used_fields[f.attname] = f
 
1235
 
 
1236
        return errors
 
1237
 
 
1238
    @classmethod
 
1239
    def _check_column_name_clashes(cls):
 
1240
        # Store a list of column names which have already been used by other fields.
 
1241
        used_column_names = []
 
1242
        errors = []
 
1243
 
 
1244
        for f in cls._meta.local_fields:
 
1245
            _, column_name = f.get_attname_column()
 
1246
 
 
1247
            # Ensure the column name is not already in use.
 
1248
            if column_name and column_name in used_column_names:
 
1249
                errors.append(
 
1250
                    checks.Error(
 
1251
                        "Field '%s' has column name '%s' that is used by another field." % (f.name, column_name),
 
1252
                        hint="Specify a 'db_column' for the field.",
 
1253
                        obj=cls,
 
1254
                        id='models.E007'
 
1255
                    )
 
1256
                )
 
1257
            else:
 
1258
                used_column_names.append(column_name)
 
1259
 
 
1260
        return errors
 
1261
 
 
1262
    @classmethod
 
1263
    def _check_index_together(cls):
 
1264
        """ Check the value of "index_together" option. """
 
1265
        if not isinstance(cls._meta.index_together, (tuple, list)):
 
1266
            return [
 
1267
                checks.Error(
 
1268
                    "'index_together' must be a list or tuple.",
 
1269
                    hint=None,
 
1270
                    obj=cls,
 
1271
                    id='models.E008',
 
1272
                )
 
1273
            ]
 
1274
 
 
1275
        elif any(not isinstance(fields, (tuple, list))
 
1276
                for fields in cls._meta.index_together):
 
1277
            return [
 
1278
                checks.Error(
 
1279
                    "All 'index_together' elements must be lists or tuples.",
 
1280
                    hint=None,
 
1281
                    obj=cls,
 
1282
                    id='models.E009',
 
1283
                )
 
1284
            ]
 
1285
 
 
1286
        else:
 
1287
            errors = []
 
1288
            for fields in cls._meta.index_together:
 
1289
                errors.extend(cls._check_local_fields(fields, "index_together"))
 
1290
            return errors
 
1291
 
 
1292
    @classmethod
 
1293
    def _check_unique_together(cls):
 
1294
        """ Check the value of "unique_together" option. """
 
1295
        if not isinstance(cls._meta.unique_together, (tuple, list)):
 
1296
            return [
 
1297
                checks.Error(
 
1298
                    "'unique_together' must be a list or tuple.",
 
1299
                    hint=None,
 
1300
                    obj=cls,
 
1301
                    id='models.E010',
 
1302
                )
 
1303
            ]
 
1304
 
 
1305
        elif any(not isinstance(fields, (tuple, list))
 
1306
                for fields in cls._meta.unique_together):
 
1307
            return [
 
1308
                checks.Error(
 
1309
                    "All 'unique_together' elements must be lists or tuples.",
 
1310
                    hint=None,
 
1311
                    obj=cls,
 
1312
                    id='models.E011',
 
1313
                )
 
1314
            ]
 
1315
 
 
1316
        else:
 
1317
            errors = []
 
1318
            for fields in cls._meta.unique_together:
 
1319
                errors.extend(cls._check_local_fields(fields, "unique_together"))
 
1320
            return errors
 
1321
 
 
1322
    @classmethod
 
1323
    def _check_local_fields(cls, fields, option):
 
1324
        from django.db import models
 
1325
 
 
1326
        errors = []
 
1327
        for field_name in fields:
 
1328
            try:
 
1329
                field = cls._meta.get_field(field_name,
 
1330
                    many_to_many=True)
 
1331
            except models.FieldDoesNotExist:
 
1332
                errors.append(
 
1333
                    checks.Error(
 
1334
                        "'%s' refers to the non-existent field '%s'." % (option, field_name),
 
1335
                        hint=None,
 
1336
                        obj=cls,
 
1337
                        id='models.E012',
 
1338
                    )
 
1339
                )
 
1340
            else:
 
1341
                if isinstance(field.rel, models.ManyToManyRel):
 
1342
                    errors.append(
 
1343
                        checks.Error(
 
1344
                            ("'%s' refers to a ManyToManyField '%s', but "
 
1345
                             "ManyToManyFields are not permitted in '%s'.") % (
 
1346
                                option, field_name, option
 
1347
                            ),
 
1348
                            hint=None,
 
1349
                            obj=cls,
 
1350
                            id='models.E013',
 
1351
                        )
 
1352
                    )
 
1353
        return errors
 
1354
 
 
1355
    @classmethod
 
1356
    def _check_ordering(cls):
 
1357
        """ Check "ordering" option -- is it a list of strings and do all fields
 
1358
        exist? """
 
1359
 
 
1360
        from django.db.models import FieldDoesNotExist
 
1361
 
 
1362
        if not cls._meta.ordering:
 
1363
            return []
 
1364
 
 
1365
        if not isinstance(cls._meta.ordering, (list, tuple)):
 
1366
            return [
 
1367
                checks.Error(
 
1368
                    ("'ordering' must be a tuple or list "
 
1369
                     "(even if you want to order by only one field)."),
 
1370
                    hint=None,
 
1371
                    obj=cls,
 
1372
                    id='models.E014',
 
1373
                )
 
1374
            ]
 
1375
 
 
1376
        errors = []
 
1377
 
 
1378
        fields = cls._meta.ordering
 
1379
 
 
1380
        # Skip '?' fields.
 
1381
        fields = (f for f in fields if f != '?')
 
1382
 
 
1383
        # Convert "-field" to "field".
 
1384
        fields = ((f[1:] if f.startswith('-') else f) for f in fields)
 
1385
 
 
1386
        fields = (f for f in fields if
 
1387
            f != '_order' or not cls._meta.order_with_respect_to)
 
1388
 
 
1389
        # Skip ordering in the format field1__field2 (FIXME: checking
 
1390
        # this format would be nice, but it's a little fiddly).
 
1391
        fields = (f for f in fields if '__' not in f)
 
1392
 
 
1393
        # Skip ordering on pk. This is always a valid order_by field
 
1394
        # but is an alias and therefore won't be found by opts.get_field.
 
1395
        fields = (f for f in fields if f != 'pk')
 
1396
 
 
1397
        for field_name in fields:
 
1398
            try:
 
1399
                cls._meta.get_field(field_name, many_to_many=False)
 
1400
            except FieldDoesNotExist:
 
1401
                if field_name.endswith('_id'):
 
1402
                    try:
 
1403
                        field = cls._meta.get_field(field_name[:-3], many_to_many=False)
 
1404
                    except FieldDoesNotExist:
 
1405
                        pass
 
1406
                    else:
 
1407
                        if field.attname == field_name:
 
1408
                            continue
 
1409
                errors.append(
 
1410
                    checks.Error(
 
1411
                        "'ordering' refers to the non-existent field '%s'." % field_name,
 
1412
                        hint=None,
 
1413
                        obj=cls,
 
1414
                        id='models.E015',
 
1415
                    )
 
1416
                )
 
1417
        return errors
 
1418
 
977
1419
 
978
1420
############################################
979
1421
# HELPER FUNCTIONS (CURRIED MODEL METHODS) #
1013
1455
# MISC #
1014
1456
########
1015
1457
 
1016
 
class Empty(object):
1017
 
    pass
1018
1458
 
1019
1459
def simple_class_factory(model, attrs):
1020
1460
    """
1022
1462
    """
1023
1463
    return model
1024
1464
 
 
1465
 
1025
1466
def model_unpickle(model_id, attrs, factory):
1026
1467
    """
1027
1468
    Used to unpickle Model subclasses with deferred fields.
1028
1469
    """
1029
1470
    if isinstance(model_id, tuple):
1030
 
        model = get_model(*model_id)
 
1471
        model = apps.get_model(*model_id)
1031
1472
    else:
1032
1473
        # Backwards compat - the model was cached directly in earlier versions.
1033
1474
        model = model_id