Loading django/db/migrations/operations/base.py +7 −9 Original line number Diff line number Diff line Loading @@ -98,17 +98,15 @@ class Operation(object): """ return self.references_model(model_name, app_label) def allowed_to_migrate(self, connection_alias, model): def allowed_to_migrate(self, connection_alias, model, hints=None): """ Returns if we're allowed to migrate the model. Checks the router, if it's a proxy, if it's managed, and if it's swapped out. Returns if we're allowed to migrate the model. """ return ( not model._meta.proxy and not model._meta.swapped and model._meta.managed and router.allow_migrate(connection_alias, model) ) # Always skip if proxy, swapped out, or unmanaged. if model and (model._meta.proxy or model._meta.swapped or not model._meta.managed): return False return router.allow_migrate(connection_alias, model, **(hints or {})) def __repr__(self): return "<%s %s%s>" % ( Loading django/db/migrations/operations/special.py +20 −10 Original line number Diff line number Diff line Loading @@ -63,10 +63,11 @@ class RunSQL(Operation): """ noop = '' def __init__(self, sql, reverse_sql=None, state_operations=None): def __init__(self, sql, reverse_sql=None, state_operations=None, hints=None): self.sql = sql self.reverse_sql = reverse_sql self.state_operations = state_operations or [] self.hints = hints or {} def deconstruct(self): kwargs = { Loading @@ -76,6 +77,8 @@ class RunSQL(Operation): kwargs['reverse_sql'] = self.reverse_sql if self.state_operations: kwargs['state_operations'] = self.state_operations if self.hints: kwargs['hints'] = self.hints return ( self.__class__.__name__, [], Loading @@ -91,11 +94,13 @@ class RunSQL(Operation): state_operation.state_forwards(app_label, state) def database_forwards(self, app_label, schema_editor, from_state, to_state): if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints): self._run_sql(schema_editor, self.sql) def database_backwards(self, app_label, schema_editor, from_state, to_state): if self.reverse_sql is None: raise NotImplementedError("You cannot reverse this operation") if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints): self._run_sql(schema_editor, self.reverse_sql) def describe(self): Loading Loading @@ -125,7 +130,7 @@ class RunPython(Operation): reduces_to_sql = False def __init__(self, code, reverse_code=None, atomic=True): def __init__(self, code, reverse_code=None, atomic=True, hints=None): self.atomic = atomic # Forwards code if not callable(code): Loading @@ -138,6 +143,7 @@ class RunPython(Operation): if not callable(reverse_code): raise ValueError("RunPython must be supplied with callable arguments") self.reverse_code = reverse_code self.hints = hints or {} def deconstruct(self): kwargs = { Loading @@ -147,6 +153,8 @@ class RunPython(Operation): kwargs['reverse_code'] = self.reverse_code if self.atomic is not True: kwargs['atomic'] = self.atomic if self.hints: kwargs['hints'] = self.hints return ( self.__class__.__name__, [], Loading @@ -163,6 +171,7 @@ class RunPython(Operation): pass def database_forwards(self, app_label, schema_editor, from_state, to_state): if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints): # We now execute the Python code in a context that contains a 'models' # object, representing the versioned models as an app registry. # We could try to override the global cache, but then people will still Loading @@ -172,6 +181,7 @@ class RunPython(Operation): def database_backwards(self, app_label, schema_editor, from_state, to_state): if self.reverse_code is None: raise NotImplementedError("You cannot reverse this operation") if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints): self.reverse_code(from_state.apps, schema_editor) def describe(self): Loading django/db/utils.py +2 −2 Original line number Diff line number Diff line Loading @@ -316,7 +316,7 @@ class ConnectionRouter(object): return allow return obj1._state.db == obj2._state.db def allow_migrate(self, db, model): def allow_migrate(self, db, model, **hints): for router in self.routers: try: try: Loading @@ -331,7 +331,7 @@ class ConnectionRouter(object): # If the router doesn't have a method, skip to the next one. pass else: allow = method(db, model) allow = method(db, model, **hints) if allow is not None: return allow return True Loading docs/ref/migration-operations.txt +18 −2 Original line number Diff line number Diff line Loading @@ -206,7 +206,7 @@ Special Operations RunSQL ------ .. class:: RunSQL(sql, reverse_sql=None, state_operations=None) .. class:: RunSQL(sql, reverse_sql=None, state_operations=None, hints=None) Allows running of arbitrary SQL on the database - useful for more advanced features of database backends that Django doesn't support directly, like Loading Loading @@ -235,6 +235,11 @@ operation here so that the autodetector still has an up-to-date state of the model (otherwise, when you next run ``makemigrations``, it won't see any operation that adds that field and so will try to run it again). The optional ``hints`` argument will be passed as ``**hints`` to the :meth:`allow_migrate` method of database routers to assist them in making routing decisions. See :ref:`topics-db-multi-db-hints` for more details on database hints. .. versionchanged:: 1.7.1 If you want to include literal percent signs in a query without parameters Loading @@ -245,6 +250,8 @@ operation that adds that field and so will try to run it again). The ability to pass parameters to the ``sql`` and ``reverse_sql`` queries was added. The ``hints`` argument was added. .. attribute:: RunSQL.noop .. versionadded:: 1.8 Loading @@ -258,7 +265,7 @@ operation that adds that field and so will try to run it again). RunPython --------- .. class:: RunPython(code, reverse_code=None, atomic=True) .. class:: RunPython(code, reverse_code=None, atomic=True, hints=None) Runs custom Python code in a historical context. ``code`` (and ``reverse_code`` if supplied) should be callable objects that accept two arguments; the first is Loading @@ -267,6 +274,15 @@ match the operation's place in the project history, and the second is an instance of :class:`SchemaEditor <django.db.backends.schema.BaseDatabaseSchemaEditor>`. The optional ``hints`` argument will be passed as ``**hints`` to the :meth:`allow_migrate` method of database routers to assist them in making a routing decision. See :ref:`topics-db-multi-db-hints` for more details on database hints. .. versionadded:: 1.8 The ``hints`` argument was added. You are advised to write the code as a separate function above the ``Migration`` class in the migration file, and just pass it to ``RunPython``. Here's an example of using ``RunPython`` to create some initial objects on a ``Country`` Loading docs/releases/1.8.txt +14 −0 Original line number Diff line number Diff line Loading @@ -462,6 +462,12 @@ Migrations attribute/method were added to ease in making ``RunPython`` and ``RunSQL`` operations reversible. * The :class:`~django.db.migrations.operations.RunPython` and :class:`~django.db.migrations.operations.RunSQL` operations now accept a ``hints`` parameter that will be passed to :meth:`allow_migrate`. To take advantage of this feature you must ensure that the ``allow_migrate()`` method of all your routers accept ``**hints``. Models ^^^^^^ Loading Loading @@ -1029,6 +1035,14 @@ Miscellaneous * :func:`django.utils.translation.get_language()` now returns ``None`` instead of :setting:`LANGUAGE_CODE` when translations are temporarily deactivated. * The migration operations :class:`~django.db.migrations.operations.RunPython` and :class:`~django.db.migrations.operations.RunSQL` now call the :meth:`allow_migrate` method of database routers. In these cases the ``model`` argument of ``allow_migrate()`` is set to ``None``, so the router must properly handle this value. This is most useful when used together with the newly introduced ``hints`` parameter for these operations, but it can also be used to disable migrations from running on a particular database. .. _deprecated-features-1.8: Features deprecated in 1.8 Loading Loading
django/db/migrations/operations/base.py +7 −9 Original line number Diff line number Diff line Loading @@ -98,17 +98,15 @@ class Operation(object): """ return self.references_model(model_name, app_label) def allowed_to_migrate(self, connection_alias, model): def allowed_to_migrate(self, connection_alias, model, hints=None): """ Returns if we're allowed to migrate the model. Checks the router, if it's a proxy, if it's managed, and if it's swapped out. Returns if we're allowed to migrate the model. """ return ( not model._meta.proxy and not model._meta.swapped and model._meta.managed and router.allow_migrate(connection_alias, model) ) # Always skip if proxy, swapped out, or unmanaged. if model and (model._meta.proxy or model._meta.swapped or not model._meta.managed): return False return router.allow_migrate(connection_alias, model, **(hints or {})) def __repr__(self): return "<%s %s%s>" % ( Loading
django/db/migrations/operations/special.py +20 −10 Original line number Diff line number Diff line Loading @@ -63,10 +63,11 @@ class RunSQL(Operation): """ noop = '' def __init__(self, sql, reverse_sql=None, state_operations=None): def __init__(self, sql, reverse_sql=None, state_operations=None, hints=None): self.sql = sql self.reverse_sql = reverse_sql self.state_operations = state_operations or [] self.hints = hints or {} def deconstruct(self): kwargs = { Loading @@ -76,6 +77,8 @@ class RunSQL(Operation): kwargs['reverse_sql'] = self.reverse_sql if self.state_operations: kwargs['state_operations'] = self.state_operations if self.hints: kwargs['hints'] = self.hints return ( self.__class__.__name__, [], Loading @@ -91,11 +94,13 @@ class RunSQL(Operation): state_operation.state_forwards(app_label, state) def database_forwards(self, app_label, schema_editor, from_state, to_state): if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints): self._run_sql(schema_editor, self.sql) def database_backwards(self, app_label, schema_editor, from_state, to_state): if self.reverse_sql is None: raise NotImplementedError("You cannot reverse this operation") if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints): self._run_sql(schema_editor, self.reverse_sql) def describe(self): Loading Loading @@ -125,7 +130,7 @@ class RunPython(Operation): reduces_to_sql = False def __init__(self, code, reverse_code=None, atomic=True): def __init__(self, code, reverse_code=None, atomic=True, hints=None): self.atomic = atomic # Forwards code if not callable(code): Loading @@ -138,6 +143,7 @@ class RunPython(Operation): if not callable(reverse_code): raise ValueError("RunPython must be supplied with callable arguments") self.reverse_code = reverse_code self.hints = hints or {} def deconstruct(self): kwargs = { Loading @@ -147,6 +153,8 @@ class RunPython(Operation): kwargs['reverse_code'] = self.reverse_code if self.atomic is not True: kwargs['atomic'] = self.atomic if self.hints: kwargs['hints'] = self.hints return ( self.__class__.__name__, [], Loading @@ -163,6 +171,7 @@ class RunPython(Operation): pass def database_forwards(self, app_label, schema_editor, from_state, to_state): if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints): # We now execute the Python code in a context that contains a 'models' # object, representing the versioned models as an app registry. # We could try to override the global cache, but then people will still Loading @@ -172,6 +181,7 @@ class RunPython(Operation): def database_backwards(self, app_label, schema_editor, from_state, to_state): if self.reverse_code is None: raise NotImplementedError("You cannot reverse this operation") if self.allowed_to_migrate(schema_editor.connection.alias, None, hints=self.hints): self.reverse_code(from_state.apps, schema_editor) def describe(self): Loading
django/db/utils.py +2 −2 Original line number Diff line number Diff line Loading @@ -316,7 +316,7 @@ class ConnectionRouter(object): return allow return obj1._state.db == obj2._state.db def allow_migrate(self, db, model): def allow_migrate(self, db, model, **hints): for router in self.routers: try: try: Loading @@ -331,7 +331,7 @@ class ConnectionRouter(object): # If the router doesn't have a method, skip to the next one. pass else: allow = method(db, model) allow = method(db, model, **hints) if allow is not None: return allow return True Loading
docs/ref/migration-operations.txt +18 −2 Original line number Diff line number Diff line Loading @@ -206,7 +206,7 @@ Special Operations RunSQL ------ .. class:: RunSQL(sql, reverse_sql=None, state_operations=None) .. class:: RunSQL(sql, reverse_sql=None, state_operations=None, hints=None) Allows running of arbitrary SQL on the database - useful for more advanced features of database backends that Django doesn't support directly, like Loading Loading @@ -235,6 +235,11 @@ operation here so that the autodetector still has an up-to-date state of the model (otherwise, when you next run ``makemigrations``, it won't see any operation that adds that field and so will try to run it again). The optional ``hints`` argument will be passed as ``**hints`` to the :meth:`allow_migrate` method of database routers to assist them in making routing decisions. See :ref:`topics-db-multi-db-hints` for more details on database hints. .. versionchanged:: 1.7.1 If you want to include literal percent signs in a query without parameters Loading @@ -245,6 +250,8 @@ operation that adds that field and so will try to run it again). The ability to pass parameters to the ``sql`` and ``reverse_sql`` queries was added. The ``hints`` argument was added. .. attribute:: RunSQL.noop .. versionadded:: 1.8 Loading @@ -258,7 +265,7 @@ operation that adds that field and so will try to run it again). RunPython --------- .. class:: RunPython(code, reverse_code=None, atomic=True) .. class:: RunPython(code, reverse_code=None, atomic=True, hints=None) Runs custom Python code in a historical context. ``code`` (and ``reverse_code`` if supplied) should be callable objects that accept two arguments; the first is Loading @@ -267,6 +274,15 @@ match the operation's place in the project history, and the second is an instance of :class:`SchemaEditor <django.db.backends.schema.BaseDatabaseSchemaEditor>`. The optional ``hints`` argument will be passed as ``**hints`` to the :meth:`allow_migrate` method of database routers to assist them in making a routing decision. See :ref:`topics-db-multi-db-hints` for more details on database hints. .. versionadded:: 1.8 The ``hints`` argument was added. You are advised to write the code as a separate function above the ``Migration`` class in the migration file, and just pass it to ``RunPython``. Here's an example of using ``RunPython`` to create some initial objects on a ``Country`` Loading
docs/releases/1.8.txt +14 −0 Original line number Diff line number Diff line Loading @@ -462,6 +462,12 @@ Migrations attribute/method were added to ease in making ``RunPython`` and ``RunSQL`` operations reversible. * The :class:`~django.db.migrations.operations.RunPython` and :class:`~django.db.migrations.operations.RunSQL` operations now accept a ``hints`` parameter that will be passed to :meth:`allow_migrate`. To take advantage of this feature you must ensure that the ``allow_migrate()`` method of all your routers accept ``**hints``. Models ^^^^^^ Loading Loading @@ -1029,6 +1035,14 @@ Miscellaneous * :func:`django.utils.translation.get_language()` now returns ``None`` instead of :setting:`LANGUAGE_CODE` when translations are temporarily deactivated. * The migration operations :class:`~django.db.migrations.operations.RunPython` and :class:`~django.db.migrations.operations.RunSQL` now call the :meth:`allow_migrate` method of database routers. In these cases the ``model`` argument of ``allow_migrate()`` is set to ``None``, so the router must properly handle this value. This is most useful when used together with the newly introduced ``hints`` parameter for these operations, but it can also be used to disable migrations from running on a particular database. .. _deprecated-features-1.8: Features deprecated in 1.8 Loading