summaryrefslogtreecommitdiff
path: root/docs/topics
diff options
context:
space:
mode:
Diffstat (limited to 'docs/topics')
-rw-r--r--docs/topics/migrations.txt80
1 files changed, 79 insertions, 1 deletions
diff --git a/docs/topics/migrations.txt b/docs/topics/migrations.txt
index f8500f2f2d..45fdc0bef0 100644
--- a/docs/topics/migrations.txt
+++ b/docs/topics/migrations.txt
@@ -60,7 +60,7 @@ Backend Support
Migrations are supported on all backends that Django ships with, as well
as any third-party backends if they have programmed in support for schema
-alteration (done via the ``SchemaEditor`` class).
+alteration (done via the :doc:`SchemaEditor </ref/schema-editor>` class).
However, some databases are more capable than others when it comes to
schema migrations; some of the caveats are covered below.
@@ -311,6 +311,84 @@ from these base classes inherit normally, so if you absolutely need access
to these you can opt to move them into a superclass.
+.. _data-migrations:
+
+Data Migrations
+---------------
+
+As well as changing the database schema, you can also use migrations to change
+the data in the database itself, in conjunction with the schema if you want.
+
+Migrations that alter data are usually called "data migrations"; they're best
+written as separate migrations, sitting alongside your schema migrations.
+
+Django can't automatically generate data migrations for you, as it does with
+schema migrations, but it's not very hard to write them. Migration files in
+Django are made up of :doc:`Operations </ref/migration-operations>`, and
+the main operation you use for data migrations is
+:ref:`RunPython <operation-run-python>`.
+
+To start, make an empty migration file you can work from (Django will put
+the file in the right place, suggest a name, and add dependencies for you)::
+
+ python manage.py makemigrations --empty yourappname
+
+Then, open up the file; it should look something like this::
+
+ # encoding: utf8
+ from django.db import models, migrations
+
+ class Migration(migrations.Migration):
+
+ dependencies = [
+ ('yourappname', '0001_initial'),
+ ]
+
+ operations = [
+ ]
+
+Now, all you need to do is create a new function and have RunPython use it.
+RunPython expects a callable as its argument which takes two arguments - the
+first is an :doc:`app registry </ref/applications/>` that has the historical
+versions of all your models loaded into it to match where in your history the
+migration sits, and the second is a :doc:`SchemaEditor </ref/schema-editor>`,
+which you can use to manually effect database schema changes (but beware,
+doing this can confuse the migration autodetector!)
+
+Let's write a simple migration that populates our new ``name`` field with the
+combined values of ``first_name`` and ``last_name`` (we've come to our senses
+and realised that not everyone has first and last names). All we
+need to do is use the historical model and iterate over the rows::
+
+ # encoding: utf8
+ from django.db import models, migrations
+
+ def combine_names(apps, schema_editor):
+ # We can't import the Person model directly as it may be a newer
+ # version than this migration expects. We use the historical version.
+ Person = apps.get_model("yourappname", "Person")
+ for person in Person.objects.all():
+ person.name = "%s %s" % (person.first_name, person.last_name)
+ person.save()
+
+ class Migration(migrations.Migration):
+
+ dependencies = [
+ ('yourappname', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RunPython(combine_names),
+ ]
+
+Once that's done, we can just run ``python manage.py migrate`` as normal and
+the data migration will run in place alongside other migrations.
+
+If you're interested in the more advanced migration operations, or want
+to be able to write your own, see our
+:doc:`migration operations reference </ref/migration-operations>`.
+
+
.. _migration-serializing:
Serializing values