[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:
Andrei Kulakov 2015-02-04 12:22:06 -05:00 committed by Tim Graham
parent 4e8b1648d0
commit 9bb451aedb

View File

@ -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