[1.7.x] Fixed #24052 -- Doc'd how to write data migrations with models in multiple apps.
Backport of b089759d6025582f36fbea3c4be3855c50b82462 from master
This commit is contained in:
parent
4e8b1648d0
commit
9bb451aedb
@ -435,68 +435,31 @@ You can pass a second callable to
|
|||||||
want executed when migrating backwards. If this callable is omitted, migrating
|
want executed when migrating backwards. If this callable is omitted, migrating
|
||||||
backwards will raise an exception.
|
backwards will raise an exception.
|
||||||
|
|
||||||
.. _data-migrations-and-multiple-databases:
|
Accessing models from other apps
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Data migrations and multiple databases
|
When writing a ``RunPython`` function that uses models from apps other than the
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
one in which the migration is located, the migration's ``dependencies``
|
||||||
|
attribute should include the latest migration of each app that is involved,
|
||||||
|
otherwise you may get an error similar to: ``LookupError: No installed app
|
||||||
|
with label 'myappname'`` when you try to retrieve the model in the ``RunPython``
|
||||||
|
function using ``apps.get_model()``.
|
||||||
|
|
||||||
When using multiple databases, you may need to figure out whether or not to
|
In the following example, we have a migration in ``app1`` which needs to use
|
||||||
run a migration against a particular database. For example, you may want to
|
models in ``app2``. We aren't concerned with the details of ``move_m1`` other
|
||||||
**only** run a migration on a particular database.
|
than the fact it will need to access models from both apps. Therefore we've
|
||||||
|
added a dependency that specifies the last migration of ``app2``::
|
||||||
In order to do that you can check the database connection's alias inside a
|
|
||||||
``RunPython`` operation by looking at the ``schema_editor.connection.alias``
|
|
||||||
attribute::
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
def forwards(apps, schema_editor):
|
|
||||||
if not schema_editor.connection.alias == 'default':
|
|
||||||
return
|
|
||||||
# Your migration code goes here
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
# Dependencies to other migrations
|
('app1', '0001_initial'),
|
||||||
|
# added dependency to enable using models from app2 in move_m1
|
||||||
|
('app2', '0004_foobar'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.RunPython(forwards),
|
migrations.RunPython(move_m1),
|
||||||
]
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
.. snippet::
|
|
||||||
:filename: myapp/dbrouters.py
|
|
||||||
|
|
||||||
class MyRouter(object):
|
|
||||||
|
|
||||||
def allow_migrate(self, db, model):
|
|
||||||
return db == 'default'
|
|
||||||
|
|
||||||
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):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
# Dependencies to other migrations
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RunPython(forwards),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
More advanced migrations
|
More advanced migrations
|
||||||
|
Loading…
x
Reference in New Issue
Block a user