Loading django/core/management/commands/makemigrations.py +5 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ from itertools import takewhile from django.apps import apps from django.core.management.base import BaseCommand, CommandError from django.db import connections from django.db.migrations import Migration from django.db.migrations.autodetector import MigrationAutodetector from django.db.migrations.loader import MigrationLoader Loading Loading @@ -75,6 +76,10 @@ class Command(BaseCommand): # the loader doesn't try to resolve replaced migrations from DB. loader = MigrationLoader(None, ignore_no_migrations=True) # Raise an error if any migrations are applied before their dependencies. for db in connections: loader.check_consistent_history(connections[db]) # Before anything else, see if there's conflicting apps and drop out # hard if there are any and they don't want to merge conflicts = loader.detect_conflicts() Loading django/core/management/commands/migrate.py +3 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,9 @@ class Command(BaseCommand): # Work out which apps have migrations and which do not executor = MigrationExecutor(connection, self.migration_progress_callback) # Raise an error if any migrations are applied before their dependencies. executor.loader.check_consistent_history(connection) # Before anything else, see if there's conflicting apps and drop out # hard if there are any conflicts = executor.loader.detect_conflicts() Loading django/db/migrations/exceptions.py +7 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,13 @@ class CircularDependencyError(Exception): pass class InconsistentMigrationHistory(Exception): """ Raised when an applied migration has some of its dependencies not applied. """ pass class InvalidBasesError(ValueError): """ Raised when a model's base classes can't be resolved. Loading django/db/migrations/loader.py +23 −1 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ from django.db.migrations.graph import MigrationGraph from django.db.migrations.recorder import MigrationRecorder from django.utils import six from .exceptions import AmbiguityError, BadMigrationError, NodeNotFoundError from .exceptions import ( AmbiguityError, BadMigrationError, InconsistentMigrationHistory, NodeNotFoundError, ) MIGRATIONS_MODULE_NAME = 'migrations' Loading Loading @@ -318,6 +321,25 @@ class MigrationLoader(object): # "child" is not in there. _reraise_missing_dependency(migration, child, e) def check_consistent_history(self, connection): """ Raise InconsistentMigrationHistory if any applied migrations have unapplied dependencies. """ recorder = MigrationRecorder(connection) applied = recorder.applied_migrations() for migration in applied: # If the migration is unknown, skip it. if migration not in self.graph.nodes: continue for parent in self.graph.node_map[migration].parents: if parent not in applied: raise InconsistentMigrationHistory( "Migration {}.{} is applied before its dependency {}.{}".format( migration[0], migration[1], parent[0], parent[1], ) ) def detect_conflicts(self): """ Looks through the loaded graph and detects any conflicts - apps Loading docs/releases/1.10.txt +4 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,10 @@ Migrations * Added support for :ref:`non-atomic migrations <non-atomic-migrations>` by setting the ``atomic`` attribute on a ``Migration``. * The ``migrate`` and ``makemigrations`` commands now check for a consistent migration history. If they find some unapplied dependencies of an applied migration, ``InconsistentMigrationHistory`` is raised. Models ~~~~~~ Loading Loading
django/core/management/commands/makemigrations.py +5 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ from itertools import takewhile from django.apps import apps from django.core.management.base import BaseCommand, CommandError from django.db import connections from django.db.migrations import Migration from django.db.migrations.autodetector import MigrationAutodetector from django.db.migrations.loader import MigrationLoader Loading Loading @@ -75,6 +76,10 @@ class Command(BaseCommand): # the loader doesn't try to resolve replaced migrations from DB. loader = MigrationLoader(None, ignore_no_migrations=True) # Raise an error if any migrations are applied before their dependencies. for db in connections: loader.check_consistent_history(connections[db]) # Before anything else, see if there's conflicting apps and drop out # hard if there are any and they don't want to merge conflicts = loader.detect_conflicts() Loading
django/core/management/commands/migrate.py +3 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,9 @@ class Command(BaseCommand): # Work out which apps have migrations and which do not executor = MigrationExecutor(connection, self.migration_progress_callback) # Raise an error if any migrations are applied before their dependencies. executor.loader.check_consistent_history(connection) # Before anything else, see if there's conflicting apps and drop out # hard if there are any conflicts = executor.loader.detect_conflicts() Loading
django/db/migrations/exceptions.py +7 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,13 @@ class CircularDependencyError(Exception): pass class InconsistentMigrationHistory(Exception): """ Raised when an applied migration has some of its dependencies not applied. """ pass class InvalidBasesError(ValueError): """ Raised when a model's base classes can't be resolved. Loading
django/db/migrations/loader.py +23 −1 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ from django.db.migrations.graph import MigrationGraph from django.db.migrations.recorder import MigrationRecorder from django.utils import six from .exceptions import AmbiguityError, BadMigrationError, NodeNotFoundError from .exceptions import ( AmbiguityError, BadMigrationError, InconsistentMigrationHistory, NodeNotFoundError, ) MIGRATIONS_MODULE_NAME = 'migrations' Loading Loading @@ -318,6 +321,25 @@ class MigrationLoader(object): # "child" is not in there. _reraise_missing_dependency(migration, child, e) def check_consistent_history(self, connection): """ Raise InconsistentMigrationHistory if any applied migrations have unapplied dependencies. """ recorder = MigrationRecorder(connection) applied = recorder.applied_migrations() for migration in applied: # If the migration is unknown, skip it. if migration not in self.graph.nodes: continue for parent in self.graph.node_map[migration].parents: if parent not in applied: raise InconsistentMigrationHistory( "Migration {}.{} is applied before its dependency {}.{}".format( migration[0], migration[1], parent[0], parent[1], ) ) def detect_conflicts(self): """ Looks through the loaded graph and detects any conflicts - apps Loading
docs/releases/1.10.txt +4 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,10 @@ Migrations * Added support for :ref:`non-atomic migrations <non-atomic-migrations>` by setting the ``atomic`` attribute on a ``Migration``. * The ``migrate`` and ``makemigrations`` commands now check for a consistent migration history. If they find some unapplied dependencies of an applied migration, ``InconsistentMigrationHistory`` is raised. Models ~~~~~~ Loading