Esempio n. 1
0
    def handle_noargs(self, **options):
        # XXX: (Temporary) workaround for ticket #1796: force early loading of all
        # models from installed apps.
        from django.core.apps import app_cache

        app_cache.get_models()

        use_plain = options.get("plain", False)
        no_startup = options.get("no_startup", False)
        interface = options.get("interface", None)

        try:
            if use_plain:
                # Don't bother loading IPython, because the user wants plain Python.
                raise ImportError

            self.run_shell(shell=interface)
        except ImportError:
            import code

            # Set up a dictionary to serve as the environment for the shell, so
            # that tab completion works on objects that are imported at runtime.
            # See ticket 5082.
            imported_objects = {}
            try:  # Try activating rlcompleter, because it's handy.
                import readline
            except ImportError:
                pass
            else:
                # We don't have to wrap the following import in a 'try', because
                # we already know 'readline' was imported successfully.
                import rlcompleter

                readline.set_completer(rlcompleter.Completer(imported_objects).complete)
                readline.parse_and_bind("tab:complete")

            # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
            # conventions and get $PYTHONSTARTUP first then .pythonrc.py.
            if not no_startup:
                for pythonrc in (os.environ.get("PYTHONSTARTUP"), "~/.pythonrc.py"):
                    if not pythonrc:
                        continue
                    pythonrc = os.path.expanduser(pythonrc)
                    if not os.path.isfile(pythonrc):
                        continue
                    try:
                        with open(pythonrc) as handle:
                            exec(compile(handle.read(), pythonrc, "exec"), imported_objects)
                    except NameError:
                        pass
            code.interact(local=imported_objects)
Esempio n. 2
0
 def get_migratable_models(self, app, db, include_auto_created=False):
     """
     Return app models allowed to be synchronized on provided db.
     """
     from django.core.apps import app_cache
     return [model for model in app_cache.get_models(app, include_auto_created=include_auto_created)
             if self.allow_migrate(db, model)]
Esempio n. 3
0
    def _build_kml_sources(self, sources):
        """
        Goes through the given sources and returns a 3-tuple of
        the application label, module name, and field name of every
        GeometryField encountered in the sources.

        If no sources are provided, then all models.
        """
        kml_sources = []
        if sources is None:
            sources = app_cache.get_models()
        for source in sources:
            if isinstance(source, models.base.ModelBase):
                for field in source._meta.fields:
                    if isinstance(field, GeometryField):
                        kml_sources.append((source._meta.app_label,
                                            source._meta.model_name,
                                            field.name))
            elif isinstance(source, (list, tuple)):
                if len(source) != 3:
                    raise ValueError('Must specify a 3-tuple of (app_label, module_name, field_name).')
                kml_sources.append(source)
            else:
                raise TypeError('KML Sources must be a model or a 3-tuple.')
        return kml_sources
Esempio n. 4
0
def create_permissions(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, **kwargs):
    try:
        app_cache.get_model('auth', 'Permission')
    except UnavailableApp:
        return

    if not router.allow_migrate(db, auth_app.Permission):
        return

    from django.contrib.contenttypes.models import ContentType

    app_models = app_cache.get_models(app)

    # This will hold the permissions we're looking for as
    # (content_type, (codename, name))
    searched_perms = list()
    # The codenames and ctypes that should exist.
    ctypes = set()
    for klass in app_models:
        # Force looking up the content types in the current database
        # before creating foreign keys to them.
        ctype = ContentType.objects.db_manager(db).get_for_model(klass)
        ctypes.add(ctype)
        for perm in _get_all_permissions(klass._meta, ctype):
            searched_perms.append((ctype, perm))

    # Find all the Permissions that have a content_type for a model we're
    # looking for.  We don't need to check for codenames since we already have
    # a list of the ones we're going to create.
    all_perms = set(auth_app.Permission.objects.using(db).filter(
        content_type__in=ctypes,
    ).values_list(
        "content_type", "codename"
    ))

    perms = [
        auth_app.Permission(codename=codename, name=name, content_type=ctype)
        for ctype, (codename, name) in searched_perms
        if (ctype.pk, codename) not in all_perms
    ]
    # Validate the permissions before bulk_creation to avoid cryptic
    # database error when the verbose_name is longer than 50 characters
    permission_name_max_length = auth_app.Permission._meta.get_field('name').max_length
    verbose_name_max_length = permission_name_max_length - 11  # len('Can change ') prefix
    for perm in perms:
        if len(perm.name) > permission_name_max_length:
            raise exceptions.ValidationError(
                "The verbose_name of %s is longer than %s characters" % (
                    perm.content_type,
                    verbose_name_max_length,
                )
            )
    auth_app.Permission.objects.using(db).bulk_create(perms)
    if verbosity >= 2:
        for perm in perms:
            print("Adding permission '%s'" % perm)
Esempio n. 5
0
 def test_dynamic_load(self):
     """
     Makes a new model at runtime and ensures it goes into the right place.
     """
     old_models = app_cache.get_models(app_cache.get_app_config("app_cache").models_module)
     # Construct a new model in a new app cache
     body = {}
     new_app_cache = BaseAppCache()
     meta_contents = {
         'app_label': "app_cache",
         'app_cache': new_app_cache,
     }
     meta = type("Meta", tuple(), meta_contents)
     body['Meta'] = meta
     body['__module__'] = TotallyNormal.__module__
     temp_model = type("SouthPonies", (models.Model,), body)
     # Make sure it appeared in the right place!
     self.assertEqual(
         old_models,
         app_cache.get_models(app_cache.get_app_config("app_cache").models_module),
     )
     self.assertEqual(new_app_cache.get_model("app_cache", "SouthPonies"), temp_model)
Esempio n. 6
0
    def test_ticket_11936(self):
        # Regression for #11936 - loading.get_models should not return deferred
        # models by default.
        # Run a couple of defer queries so that app-cache must contain some
        # deferred classes. It might contain a lot more classes depending on
        # the order the tests are ran.
        list(Item.objects.defer("name"))
        list(Child.objects.defer("value"))
        klasses = set(
            map(
                attrgetter("__name__"),
                app_cache.get_models(app_cache.get_app_config("defer_regress").models_module)
            )
        )
        self.assertIn("Child", klasses)
        self.assertIn("Item", klasses)
        self.assertNotIn("Child_Deferred_value", klasses)
        self.assertNotIn("Item_Deferred_name", klasses)
        self.assertFalse(any(
            k._deferred for k in app_cache.get_models(app_cache.get_app_config("defer_regress").models_module)))

        klasses_with_deferred = set(
            map(
                attrgetter("__name__"),
                app_cache.get_models(
                    app_cache.get_app_config("defer_regress").models_module, include_deferred=True
                ),
            )
        )
        self.assertIn("Child", klasses_with_deferred)
        self.assertIn("Item", klasses_with_deferred)
        self.assertIn("Child_Deferred_value", klasses_with_deferred)
        self.assertIn("Item_Deferred_name", klasses_with_deferred)
        self.assertTrue(any(
            k._deferred for k in app_cache.get_models(
                app_cache.get_app_config("defer_regress").models_module, include_deferred=True))
        )
Esempio n. 7
0
def sql_create(app, style, connection):
    "Returns a list of the CREATE TABLE SQL statements for the given app."

    if connection.settings_dict['ENGINE'] == 'django.db.backends.dummy':
        # This must be the "dummy" database backend, which means the user
        # hasn't set ENGINE for the database.
        raise CommandError("Django doesn't know which syntax to use for your SQL statements,\n" +
            "because you haven't properly specified the ENGINE setting for the database.\n" +
            "see: https://docs.djangoproject.com/en/dev/ref/settings/#databases")

    # Get installed models, so we generate REFERENCES right.
    # We trim models from the current app so that the sqlreset command does not
    # generate invalid SQL (leaving models out of known_models is harmless, so
    # we can be conservative).
    app_models = app_cache.get_models(app, include_auto_created=True)
    final_output = []
    tables = connection.introspection.table_names()
    known_models = set(model for model in connection.introspection.installed_models(tables) if model not in app_models)
    pending_references = {}

    for model in router.get_migratable_models(app, connection.alias, include_auto_created=True):
        output, references = connection.creation.sql_create_model(model, style, known_models)
        final_output.extend(output)
        for refto, refs in references.items():
            pending_references.setdefault(refto, []).extend(refs)
            if refto in known_models:
                final_output.extend(connection.creation.sql_for_pending_references(refto, style, pending_references))
        final_output.extend(connection.creation.sql_for_pending_references(model, style, pending_references))
        # Keep track of the fact that we've created the table for this model.
        known_models.add(model)

    # Handle references to tables that are from other apps
    # but don't exist physically.
    not_installed_models = set(pending_references.keys())
    if not_installed_models:
        alter_sql = []
        for model in not_installed_models:
            alter_sql.extend(['-- ' + sql for sql in
                connection.creation.sql_for_pending_references(model, style, pending_references)])
        if alter_sql:
            final_output.append('-- The following references should be added but depend on non-existent tables:')
            final_output.extend(alter_sql)

    return final_output
Esempio n. 8
0
def check_boolean_field_default_value():
    """
    Checks if there are any BooleanFields without a default value, &
    warns the user that the default has changed from False to Null.
    """
    fields = []
    for cls in app_cache.get_models():
        opts = cls._meta
        for f in opts.local_fields:
            if isinstance(f, models.BooleanField) and not f.has_default():
                fields.append(
                    '%s.%s: "%s"' % (opts.app_label, opts.object_name, f.name)
                )
    if fields:
        fieldnames = ", ".join(fields)
        message = [
            "You have not set a default value for one or more BooleanFields:",
            "%s." % fieldnames,
            "In Django 1.6 the default value of BooleanField was changed from",
            "False to Null when Field.default isn't defined. See",
            "https://docs.djangoproject.com/en/1.6/ref/models/fields/#booleanfield"
            "for more information."
        ]
        return ' '.join(message)
Esempio n. 9
0
 def get_context_data(self, **kwargs):
     m_list = [m._meta for m in app_cache.get_models()]
     kwargs.update({'models': m_list})
     return super(ModelIndexView, self).get_context_data(**kwargs)
Esempio n. 10
0
def sort_dependencies(app_list):
    """Sort a list of app,modellist pairs into a single list of models.

    The single list of models is sorted so that any model with a natural key
    is serialized before a normal model, and any model with a natural key
    dependency has it's dependencies serialized first.
    """
    from django.core.apps import app_cache
    # Process the list of models, and get the list of dependencies
    model_dependencies = []
    models = set()
    for app, model_list in app_list:
        if model_list is None:
            model_list = app_cache.get_models(app)

        for model in model_list:
            models.add(model)
            # Add any explicitly defined dependencies
            if hasattr(model, 'natural_key'):
                deps = getattr(model.natural_key, 'dependencies', [])
                if deps:
                    deps = [app_cache.get_model(*d.split('.')) for d in deps]
            else:
                deps = []

            # Now add a dependency for any FK or M2M relation with
            # a model that defines a natural key
            for field in model._meta.fields:
                if hasattr(field.rel, 'to'):
                    rel_model = field.rel.to
                    if hasattr(rel_model, 'natural_key') and rel_model != model:
                        deps.append(rel_model)
            for field in model._meta.many_to_many:
                rel_model = field.rel.to
                if hasattr(rel_model, 'natural_key') and rel_model != model:
                    deps.append(rel_model)
            model_dependencies.append((model, deps))

    model_dependencies.reverse()
    # Now sort the models to ensure that dependencies are met. This
    # is done by repeatedly iterating over the input list of models.
    # If all the dependencies of a given model are in the final list,
    # that model is promoted to the end of the final list. This process
    # continues until the input list is empty, or we do a full iteration
    # over the input models without promoting a model to the final list.
    # If we do a full iteration without a promotion, that means there are
    # circular dependencies in the list.
    model_list = []
    while model_dependencies:
        skipped = []
        changed = False
        while model_dependencies:
            model, deps = model_dependencies.pop()

            # If all of the models in the dependency list are either already
            # on the final model list, or not on the original serialization list,
            # then we've found another model with all it's dependencies satisfied.
            found = True
            for candidate in ((d not in models or d in model_list) for d in deps):
                if not candidate:
                    found = False
            if found:
                model_list.append(model)
                changed = True
            else:
                skipped.append((model, deps))
        if not changed:
            raise CommandError("Can't resolve dependencies for %s in serialized app list." %
                ', '.join('%s.%s' % (model._meta.app_label, model._meta.object_name)
                for model, deps in sorted(skipped, key=lambda obj: obj[0].__name__))
            )
        model_dependencies = skipped

    return model_list
Esempio n. 11
0
 def handle_app(self, app, **options):
     connection = connections[options.get('database')]
     return '\n'.join(connection.ops.sequence_reset_sql(self.style, app_cache.get_models(app, include_auto_created=True)))
Esempio n. 12
0
def update_contenttypes(app, created_models, verbosity=2, db=DEFAULT_DB_ALIAS, **kwargs):
    """
    Creates content types for models in the given app, removing any model
    entries that no longer have a matching model class.
    """
    try:
        app_cache.get_model('contenttypes', 'ContentType')
    except UnavailableApp:
        return

    if not router.allow_migrate(db, ContentType):
        return

    ContentType.objects.clear_cache()
    app_models = app_cache.get_models(app)
    if not app_models:
        return
    # They all have the same app_label, get the first one.
    app_label = app_models[0]._meta.app_label
    app_models = dict(
        (model._meta.model_name, model)
        for model in app_models
    )

    # Get all the content types
    content_types = dict(
        (ct.model, ct)
        for ct in ContentType.objects.using(db).filter(app_label=app_label)
    )
    to_remove = [
        ct
        for (model_name, ct) in six.iteritems(content_types)
        if model_name not in app_models
    ]

    cts = [
        ContentType(
            name=smart_text(model._meta.verbose_name_raw),
            app_label=app_label,
            model=model_name,
        )
        for (model_name, model) in six.iteritems(app_models)
        if model_name not in content_types
    ]
    ContentType.objects.using(db).bulk_create(cts)
    if verbosity >= 2:
        for ct in cts:
            print("Adding content type '%s | %s'" % (ct.app_label, ct.model))

    # Confirm that the content type is stale before deletion.
    if to_remove:
        if kwargs.get('interactive', False):
            content_type_display = '\n'.join(
                '    %s | %s' % (ct.app_label, ct.model)
                for ct in to_remove
            )
            ok_to_delete = input("""The following content types are stale and need to be deleted:

%s

Any objects related to these content types by a foreign key will also
be deleted. Are you sure you want to delete these content types?
If you're unsure, answer 'no'.

    Type 'yes' to continue, or 'no' to cancel: """ % content_type_display)
        else:
            ok_to_delete = False

        if ok_to_delete == 'yes':
            for ct in to_remove:
                if verbosity >= 2:
                    print("Deleting stale content type '%s | %s'" % (ct.app_label, ct.model))
                ct.delete()
        else:
            if verbosity >= 2:
                print("Stale content types remain.")
Esempio n. 13
0
 def test_get_models_with_not_installed(self):
     self.assertTrue(
         "NotInstalledModel" in [
             m.__name__ for m in app_cache.get_models(only_installed=False)])
Esempio n. 14
0
 def test_get_models_with_app_label_only_returns_installed_models(self):
     self.assertEqual(app_cache.get_models(self.not_installed_module), [])
Esempio n. 15
0
 def test_get_models_only_returns_installed_models(self):
     self.assertFalse(
         "NotInstalledModel" in
         [m.__name__ for m in app_cache.get_models()])
Esempio n. 16
0
def get_validation_errors(outfile, app=None):
    """
    Validates all models that are part of the specified app. If no app name is provided,
    validates all models of all installed apps. Writes errors, if any, to outfile.
    Returns number of errors.
    """
    from django.core.apps import app_cache
    from django.db import connection, models
    from django.db.models.deletion import SET_NULL, SET_DEFAULT

    e = ModelErrorCollection(outfile)

    for cls in app_cache.get_models(app, include_swapped=True):
        opts = cls._meta

        # Check swappable attribute.
        if opts.swapped:
            try:
                app_label, model_name = opts.swapped.split('.')
            except ValueError:
                e.add(opts, "%s is not of the form 'app_label.app_name'." % opts.swappable)
                continue
            if not app_cache.get_model(app_label, model_name):
                e.add(opts, "Model has been swapped out for '%s' which has not been installed or is abstract." % opts.swapped)
            # No need to perform any other validation checks on a swapped model.
            continue

        # If this is the current User model, check known validation problems with User models
        if settings.AUTH_USER_MODEL == '%s.%s' % (opts.app_label, opts.object_name):
            # Check that REQUIRED_FIELDS is a list
            if not isinstance(cls.REQUIRED_FIELDS, (list, tuple)):
                e.add(opts, 'The REQUIRED_FIELDS must be a list or tuple.')

            # Check that the USERNAME FIELD isn't included in REQUIRED_FIELDS.
            if cls.USERNAME_FIELD in cls.REQUIRED_FIELDS:
                e.add(opts, 'The field named as the USERNAME_FIELD should not be included in REQUIRED_FIELDS on a swappable User model.')

            # Check that the username field is unique
            if not opts.get_field(cls.USERNAME_FIELD).unique:
                e.add(opts, 'The USERNAME_FIELD must be unique. Add unique=True to the field parameters.')

        # Store a list of column names which have already been used by other fields.
        used_column_names = []

        # Model isn't swapped; do field-specific validation.
        for f in opts.local_fields:
            if f.name == 'id' and not f.primary_key and opts.pk.name == 'id':
                e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name)
            if f.name.endswith('_'):
                e.add(opts, '"%s": Field names cannot end with underscores, because this would lead to ambiguous queryset filters.' % f.name)
            if (f.primary_key and f.null and
                    not connection.features.interprets_empty_strings_as_nulls):
                # We cannot reliably check this for backends like Oracle which
                # consider NULL and '' to be equal (and thus set up
                # character-based fields a little differently).
                e.add(opts, '"%s": Primary key fields cannot have null=True.' % f.name)

            # Column name validation.
            # Determine which column name this field wants to use.
            _, column_name = f.get_attname_column()

            # Ensure the column name is not already in use.
            if column_name and column_name in used_column_names:
                e.add(opts, "Field '%s' has column name '%s' that is already used." % (f.name, column_name))
            else:
                used_column_names.append(column_name)

            if isinstance(f, models.CharField):
                try:
                    max_length = int(f.max_length)
                    if max_length <= 0:
                        e.add(opts, '"%s": CharFields require a "max_length" attribute that is a positive integer.' % f.name)
                except (ValueError, TypeError):
                    e.add(opts, '"%s": CharFields require a "max_length" attribute that is a positive integer.' % f.name)
            if isinstance(f, models.DecimalField):
                decimalp_ok, mdigits_ok = False, False
                decimalp_msg = '"%s": DecimalFields require a "decimal_places" attribute that is a non-negative integer.'
                try:
                    decimal_places = int(f.decimal_places)
                    if decimal_places < 0:
                        e.add(opts, decimalp_msg % f.name)
                    else:
                        decimalp_ok = True
                except (ValueError, TypeError):
                    e.add(opts, decimalp_msg % f.name)
                mdigits_msg = '"%s": DecimalFields require a "max_digits" attribute that is a positive integer.'
                try:
                    max_digits = int(f.max_digits)
                    if max_digits <= 0:
                        e.add(opts, mdigits_msg % f.name)
                    else:
                        mdigits_ok = True
                except (ValueError, TypeError):
                    e.add(opts, mdigits_msg % f.name)
                invalid_values_msg = '"%s": DecimalFields require a "max_digits" attribute value that is greater than or equal to the value of the "decimal_places" attribute.'
                if decimalp_ok and mdigits_ok:
                    if decimal_places > max_digits:
                        e.add(opts, invalid_values_msg % f.name)
            if isinstance(f, models.ImageField):
                try:
                    from django.utils.image import Image  # NOQA
                except ImportError:
                    e.add(opts, '"%s": To use ImageFields, you need to install Pillow. Get it at https://pypi.python.org/pypi/Pillow.' % f.name)
            if isinstance(f, models.BooleanField) and getattr(f, 'null', False):
                e.add(opts, '"%s": BooleanFields do not accept null values. Use a NullBooleanField instead.' % f.name)
            if isinstance(f, models.FilePathField) and not (f.allow_files or f.allow_folders):
                e.add(opts, '"%s": FilePathFields must have either allow_files or allow_folders set to True.' % f.name)
            if isinstance(f, models.GenericIPAddressField) and not getattr(f, 'null', False) and getattr(f, 'blank', False):
                e.add(opts, '"%s": GenericIPAddressField can not accept blank values if null values are not allowed, as blank values are stored as null.' % f.name)
            if f.choices:
                if isinstance(f.choices, six.string_types) or not is_iterable(f.choices):
                    e.add(opts, '"%s": "choices" should be iterable (e.g., a tuple or list).' % f.name)
                else:
                    for c in f.choices:
                        if isinstance(c, six.string_types) or not is_iterable(c) or len(c) != 2:
                            e.add(opts, '"%s": "choices" should be a sequence of two-item iterables (e.g. list of 2 item tuples).' % f.name)
            if f.db_index not in (None, True, False):
                e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name)

            # Perform any backend-specific field validation.
            connection.validation.validate_field(e, opts, f)

            # Check if the on_delete behavior is sane
            if f.rel and hasattr(f.rel, 'on_delete'):
                if f.rel.on_delete == SET_NULL and not f.null:
                    e.add(opts, "'%s' specifies on_delete=SET_NULL, but cannot be null." % f.name)
                elif f.rel.on_delete == SET_DEFAULT and not f.has_default():
                    e.add(opts, "'%s' specifies on_delete=SET_DEFAULT, but has no default value." % f.name)

            # Check to see if the related field will clash with any existing
            # fields, m2m fields, m2m related objects or related objects
            if f.rel:
                if f.rel.to not in app_cache.get_models():
                    # If the related model is swapped, provide a hint;
                    # otherwise, the model just hasn't been installed.
                    if not isinstance(f.rel.to, six.string_types) and f.rel.to._meta.swapped:
                        e.add(opts, "'%s' defines a relation with the model '%s.%s', which has been swapped out. Update the relation to point at settings.%s." % (f.name, f.rel.to._meta.app_label, f.rel.to._meta.object_name, f.rel.to._meta.swappable))
                    else:
                        e.add(opts, "'%s' has a relation with model %s, which has either not been installed or is abstract." % (f.name, f.rel.to))
                # it is a string and we could not find the model it refers to
                # so skip the next section
                if isinstance(f.rel.to, six.string_types):
                    continue

                # Make sure the related field specified by a ForeignKey is unique
                if f.requires_unique_target:
                    if len(f.foreign_related_fields) > 1:
                        has_unique_field = False
                        for rel_field in f.foreign_related_fields:
                            has_unique_field = has_unique_field or rel_field.unique
                        if not has_unique_field:
                            e.add(opts, "Field combination '%s' under model '%s' must have a unique=True constraint" % (','.join(rel_field.name for rel_field in f.foreign_related_fields), f.rel.to.__name__))
                    else:
                        if not f.foreign_related_fields[0].unique:
                            e.add(opts, "Field '%s' under model '%s' must have a unique=True constraint." % (f.foreign_related_fields[0].name, f.rel.to.__name__))

                rel_opts = f.rel.to._meta
                rel_name = f.related.get_accessor_name()
                rel_query_name = f.related_query_name()
                if not f.rel.is_hidden():
                    for r in rel_opts.fields:
                        if r.name == rel_name:
                            e.add(opts, "Accessor for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                        if r.name == rel_query_name:
                            e.add(opts, "Reverse query name for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                    for r in rel_opts.local_many_to_many:
                        if r.name == rel_name:
                            e.add(opts, "Accessor for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                        if r.name == rel_query_name:
                            e.add(opts, "Reverse query name for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                    for r in rel_opts.get_all_related_many_to_many_objects():
                        if r.get_accessor_name() == rel_name:
                            e.add(opts, "Accessor for field '%s' clashes with accessor for field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, r.model._meta.object_name, r.field.name, f.name))
                        if r.get_accessor_name() == rel_query_name:
                            e.add(opts, "Reverse query name for field '%s' clashes with accessor for field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, r.model._meta.object_name, r.field.name, f.name))
                    for r in rel_opts.get_all_related_objects():
                        if r.field is not f:
                            if r.get_accessor_name() == rel_name:
                                e.add(opts, "Accessor for field '%s' clashes with accessor for field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, r.model._meta.object_name, r.field.name, f.name))
                            if r.get_accessor_name() == rel_query_name:
                                e.add(opts, "Reverse query name for field '%s' clashes with accessor for field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, r.model._meta.object_name, r.field.name, f.name))

        seen_intermediary_signatures = []
        for i, f in enumerate(opts.local_many_to_many):
            # Check to see if the related m2m field will clash with any
            # existing fields, m2m fields, m2m related objects or related
            # objects
            if f.rel.to not in app_cache.get_models():
                # If the related model is swapped, provide a hint;
                # otherwise, the model just hasn't been installed.
                if not isinstance(f.rel.to, six.string_types) and f.rel.to._meta.swapped:
                    e.add(opts, "'%s' defines a relation with the model '%s.%s', which has been swapped out. Update the relation to point at settings.%s." % (f.name, f.rel.to._meta.app_label, f.rel.to._meta.object_name, f.rel.to._meta.swappable))
                else:
                    e.add(opts, "'%s' has an m2m relation with model %s, which has either not been installed or is abstract." % (f.name, f.rel.to))

                # it is a string and we could not find the model it refers to
                # so skip the next section
                if isinstance(f.rel.to, six.string_types):
                    continue

            # Check that the field is not set to unique.  ManyToManyFields do not support unique.
            if f.unique:
                e.add(opts, "ManyToManyFields cannot be unique.  Remove the unique argument on '%s'." % f.name)

            if f.rel.through is not None and not isinstance(f.rel.through, six.string_types):
                from_model, to_model = cls, f.rel.to
                if from_model == to_model and f.rel.symmetrical and not f.rel.through._meta.auto_created:
                    e.add(opts, "Many-to-many fields with intermediate tables cannot be symmetrical.")
                seen_from, seen_to, seen_self = False, False, 0
                for inter_field in f.rel.through._meta.fields:
                    rel_to = getattr(inter_field.rel, 'to', None)
                    if from_model == to_model:  # relation to self
                        if rel_to == from_model:
                            seen_self += 1
                        if seen_self > 2:
                            e.add(opts, "Intermediary model %s has more than "
                                "two foreign keys to %s, which is ambiguous "
                                "and is not permitted." % (
                                    f.rel.through._meta.object_name,
                                    from_model._meta.object_name
                                )
                            )
                    else:
                        if rel_to == from_model:
                            if seen_from:
                                e.add(opts, "Intermediary model %s has more "
                                    "than one foreign key to %s, which is "
                                    "ambiguous and is not permitted." % (
                                        f.rel.through._meta.object_name,
                                        from_model._meta.object_name
                                    )
                                )
                            else:
                                seen_from = True
                        elif rel_to == to_model:
                            if seen_to:
                                e.add(opts, "Intermediary model %s has more "
                                    "than one foreign key to %s, which is "
                                    "ambiguous and is not permitted." % (
                                        f.rel.through._meta.object_name,
                                        rel_to._meta.object_name
                                    )
                                )
                            else:
                                seen_to = True
                if f.rel.through not in app_cache.get_models(include_auto_created=True):
                    e.add(opts, "'%s' specifies an m2m relation through model "
                        "%s, which has not been installed." % (f.name, f.rel.through))
                signature = (f.rel.to, cls, f.rel.through)
                if signature in seen_intermediary_signatures:
                    e.add(opts, "The model %s has two manually-defined m2m "
                        "relations through the model %s, which is not "
                        "permitted. Please consider using an extra field on "
                        "your intermediary model instead." % (
                            cls._meta.object_name,
                            f.rel.through._meta.object_name
                        )
                    )
                else:
                    seen_intermediary_signatures.append(signature)
                if not f.rel.through._meta.auto_created:
                    seen_related_fk, seen_this_fk = False, False
                    for field in f.rel.through._meta.fields:
                        if field.rel:
                            if not seen_related_fk and field.rel.to == f.rel.to:
                                seen_related_fk = True
                            elif field.rel.to == cls:
                                seen_this_fk = True
                    if not seen_related_fk or not seen_this_fk:
                        e.add(opts, "'%s' is a manually-defined m2m relation "
                            "through model %s, which does not have foreign keys "
                            "to %s and %s" % (
                                f.name, f.rel.through._meta.object_name,
                                f.rel.to._meta.object_name, cls._meta.object_name
                            )
                        )
            elif isinstance(f.rel.through, six.string_types):
                e.add(opts, "'%s' specifies an m2m relation through model %s, "
                    "which has not been installed" % (f.name, f.rel.through))

            rel_opts = f.rel.to._meta
            rel_name = f.related.get_accessor_name()
            rel_query_name = f.related_query_name()
            # If rel_name is none, there is no reverse accessor (this only
            # occurs for symmetrical m2m relations to self). If this is the
            # case, there are no clashes to check for this field, as there are
            # no reverse descriptors for this field.
            if not f.rel.is_hidden():
                for r in rel_opts.fields:
                    if r.name == rel_name:
                        e.add(opts, "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(opts, "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.local_many_to_many:
                    if r.name == rel_name:
                        e.add(opts, "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                    if r.name == rel_query_name:
                        e.add(opts, "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name))
                for r in rel_opts.get_all_related_many_to_many_objects():
                    if r.field is not f:
                        if r.get_accessor_name() == rel_name:
                            e.add(opts, "Accessor for m2m field '%s' clashes with accessor for m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, r.model._meta.object_name, r.field.name, f.name))
                        if r.get_accessor_name() == rel_query_name:
                            e.add(opts, "Reverse query name for m2m field '%s' clashes with accessor for m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, r.model._meta.object_name, r.field.name, f.name))
                for r in rel_opts.get_all_related_objects():
                    if r.get_accessor_name() == rel_name:
                        e.add(opts, "Accessor for m2m field '%s' clashes with accessor for field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, r.model._meta.object_name, r.field.name, f.name))
                    if r.get_accessor_name() == rel_query_name:
                        e.add(opts, "Reverse query name for m2m field '%s' clashes with accessor for field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, r.model._meta.object_name, r.field.name, f.name))

        # Check ordering attribute.
        if opts.ordering:
            for field_name in opts.ordering:
                if field_name == '?':
                    continue
                if field_name.startswith('-'):
                    field_name = field_name[1:]
                if opts.order_with_respect_to and field_name == '_order':
                    continue
                # Skip ordering in the format field1__field2 (FIXME: checking
                # this format would be nice, but it's a little fiddly).
                if '__' in field_name:
                    continue
                # Skip ordering on pk. This is always a valid order_by field
                # but is an alias and therefore won't be found by opts.get_field.
                if field_name == 'pk':
                    continue
                try:
                    opts.get_field(field_name, many_to_many=False)
                except models.FieldDoesNotExist:
                    e.add(opts, '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name)

        # Check unique_together.
        for ut in opts.unique_together:
            validate_local_fields(e, opts, "unique_together", ut)
        if not isinstance(opts.index_together, collections.Sequence):
            e.add(opts, '"index_together" must a sequence')
        else:
            for it in opts.index_together:
                validate_local_fields(e, opts, "index_together", it)

    validate_model_signals(e)

    return len(e.errors)