mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
Fixed #22583 -- Allowed RunPython and RunSQL to provide hints to the db router.
Thanks Markus Holtermann and Tim Graham for the review.
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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``
|
||||
|
||||
@@ -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
|
||||
^^^^^^
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -150,7 +150,7 @@ A database Router is a class that provides up to four methods:
|
||||
used by foreign key and many to many operations to determine if a
|
||||
relation should be allowed between two objects.
|
||||
|
||||
.. method:: allow_migrate(db, model)
|
||||
.. method:: allow_migrate(db, model, **hints)
|
||||
|
||||
Determine if the ``model`` should have tables/indexes created in the
|
||||
database with alias ``db``. Return True if the model should be
|
||||
@@ -293,7 +293,7 @@ send queries for the ``auth`` app to ``auth_db``::
|
||||
return True
|
||||
return None
|
||||
|
||||
def allow_migrate(self, db, model):
|
||||
def allow_migrate(self, db, model, **hints):
|
||||
"""
|
||||
Make sure the auth app only appears in the 'auth_db'
|
||||
database.
|
||||
@@ -333,7 +333,7 @@ from::
|
||||
return True
|
||||
return None
|
||||
|
||||
def allow_migrate(self, db, model):
|
||||
def allow_migrate(self, db, model, **hints):
|
||||
"""
|
||||
All non-auth models end up in this pool.
|
||||
"""
|
||||
|
||||
@@ -545,28 +545,26 @@ attribute::
|
||||
migrations.RunPython(forwards),
|
||||
]
|
||||
|
||||
You can also use your database router's ``allow_migrate()`` method, but keep in
|
||||
mind that the imported router needs to stay around as long as it is referenced
|
||||
inside a migration:
|
||||
.. versionadded:: 1.8
|
||||
|
||||
You can also provide hints that will be passed to the :meth:`allow_migrate()`
|
||||
method of database routers as ``**hints``:
|
||||
|
||||
.. snippet::
|
||||
:filename: myapp/dbrouters.py
|
||||
|
||||
class MyRouter(object):
|
||||
|
||||
def allow_migrate(self, db, model):
|
||||
return db == 'default'
|
||||
def allow_migrate(self, db, model, **hints):
|
||||
if 'target_db' in hints:
|
||||
return db == hints['target_db']
|
||||
return True
|
||||
|
||||
Then, to leverage this in your migrations, do the following::
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from myappname.dbrouters import MyRouter
|
||||
|
||||
def forwards(apps, schema_editor):
|
||||
MyModel = apps.get_model("myappname", "MyModel")
|
||||
if not MyRouter().allow_migrate(schema_editor.connection.alias, MyModel):
|
||||
return
|
||||
# Your migration code goes here
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
@@ -576,7 +574,7 @@ Then, to leverage this in your migrations, do the following::
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forwards),
|
||||
migrations.RunPython(forwards, hints={'target_db': 'default'}),
|
||||
]
|
||||
|
||||
More advanced migrations
|
||||
|
||||
Reference in New Issue
Block a user