瀏覽代碼

Fixed #24016 -- Added documentation about third-party app data migrations

There was confusion about how to migrate data from third-party

applications when you are going to uninstall the application later on.

Thanks to Markus, Marten and Sergei for help and review.
rixx 9 年之前
父節點
當前提交
b7ea494d65
共有 2 個文件被更改,包括 62 次插入0 次删除
  1. 1 0
      AUTHORS
  2. 61 0
      docs/howto/writing-migrations.txt

+ 1 - 0
AUTHORS

@@ -713,6 +713,7 @@ answer newbie questions, and generally made Django that much better:
     Tim Graham <timograham@gmail.com>
     Tim Heap <tim@timheap.me>
     Tim Saylor <tim.saylor@gmail.com>
+    Tobias Kunze <rixx@cutebit.de>
     Tobias McNulty <http://www.caktusgroup.com/blog>
     tobias@neuyork.de
     Todd O'Bryan <toddobryan@mac.com>

+ 61 - 0
docs/howto/writing-migrations.txt

@@ -271,3 +271,64 @@ Prefer using ``dependencies`` over ``run_before`` when possible. You should
 only use ``run_before`` if it is undesirable or impractical to specify
 ``dependencies`` in the migration which you want to run after the one you are
 writing.
+
+Migrating data when replacing an external app
+=============================================
+
+If you plan to move from one external application to another one with a similar
+data structure, you can use a data migration. If you plan to remove the old 
+application later, you will need to set the ``dependencies`` property
+dynamically. Otherwise you will have missing dependencies once you uninstall
+the old application.
+
+.. snippet::
+    :filename: myapp/migrations/0124_ensure_dependencies.py
+
+    from django.apps import apps as global_apps
+    from django.db import migrations
+
+    def forward(apps, schema_editor):
+        """
+        see below
+        """
+
+    class Migration(migrations.Migration):
+
+        operations = [
+            migrations.RunPython(forward, migrations.RunPython.noop),
+        ]
+        dependencies = [
+            ('myapp', '0123_the_previous_migration'),
+            ('new_external_app', '0001_initial'),
+        ]
+
+        if global_apps.is_installed('old_external_app'):
+            dependencies.append(('old_external_app', '0001_initial'))
+
+In your data migration method, you will need to test for the old application
+model:
+
+.. snippet::
+    :filename: myapp/migrations/0124_ensure_dependencies.py
+
+    def forward(apps, schema_editor):
+        try:
+            OldModel = apps.get_model('old_external', 'OldModel')
+        except LookupError:
+            return
+
+        NewModel = apps.get_model('new_external', 'NewModel')
+        NewModel.objects.bulk_create(
+            NewModel(new_attribute=old_object.old_attribute)
+            for old_object in OldModel.objects.all()
+        )
+
+This way you can deploy your application anywhere without first installing
+and then uninstalling your old external dependency. If the old external
+dependency is not installed when the migration runs it will just do nothing
+instead of migrating the data.
+
+Please take also into consideration what you want to happen when the migration
+is unapplied - you could either do nothing or remove some or all data from
+the new application model; adjust the second argument of the
+:mod:`~django.db.migrations.operations.RunPython` operation accordingly.