123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- ====================
- Migration Operations
- ====================
- .. module:: django.db.migrations.operations
- Migration files are composed of one or more ``Operation``\s, objects that
- declaratively record what the migration should do to your database.
- Django also uses these ``Operation`` objects to work out what your models
- looked like historically, and to calculate what changes you've made to
- your models since the last migration so it can automatically write
- your migrations; that's why they're declarative, as it means Django can
- easily load them all into memory and run through them without touching
- the database to work out what your project should look like.
- There are also more specialized ``Operation`` objects which are for things like
- :ref:`data migrations <data-migrations>` and for advanced manual database
- manipulation. You can also write your own ``Operation`` classes if you want
- to encapsulate a custom change you commonly make.
- If you need an empty migration file to write your own ``Operation`` objects
- into, just use ``python manage.py makemigrations --empty yourappname``,
- but be aware that manually adding schema-altering operations can confuse the
- migration autodetector and make resulting runs of :djadmin:`makemigrations`
- output incorrect code.
- All of the core Django operations are available from the
- ``django.db.migrations.operations`` module.
- For introductory material, see the :doc:`migrations topic guide
- </topics/migrations>`.
- Schema Operations
- =================
- CreateModel
- -----------
- .. class:: CreateModel(name, fields, options=None, bases=None, managers=None)
- Creates a new model in the project history and a corresponding table in the
- database to match it.
- ``name`` is the model name, as would be written in the ``models.py`` file.
- ``fields`` is a list of 2-tuples of ``(field_name, field_instance)``.
- The field instance should be an unbound field (so just ``models.CharField()``,
- rather than a field takes from another model).
- ``options`` is an optional dictionary of values from the model's ``Meta`` class.
- ``bases`` is an optional list of other classes to have this model inherit from;
- it can contain both class objects as well as strings in the format
- ``"appname.ModelName"`` if you want to depend on another model (so you inherit
- from the historical version). If it's not supplied, it defaults to just
- inheriting from the standard ``models.Model``.
- ``managers`` takes a list of 2-tuples of ``(manager_name, manager_instance)``.
- The first manager in the list will be the default manager for this model during
- migrations.
- .. versionchanged:: 1.8
- The ``managers`` argument was added.
- DeleteModel
- -----------
- .. class:: DeleteModel(name)
- Deletes the model from the project history and its table from the database.
- RenameModel
- -----------
- .. class:: RenameModel(old_name, new_name)
- Renames the model from an old name to a new one.
- You may have to manually add
- this if you change the model's name and quite a few of its fields at once; to
- the autodetector, this will look like you deleted a model with the old name
- and added a new one with a different name, and the migration it creates will
- lose any data in the old table.
- AlterModelTable
- ---------------
- .. class:: AlterModelTable(name, table)
- Changes the model's table name (the :attr:`~django.db.models.Options.db_table`
- option on the ``Meta`` subclass).
- AlterUniqueTogether
- -------------------
- .. class:: AlterUniqueTogether(name, unique_together)
- Changes the model's set of unique constraints (the
- :attr:`~django.db.models.Options.unique_together` option on the ``Meta``
- subclass).
- AlterIndexTogether
- ------------------
- .. class:: AlterIndexTogether(name, index_together)
- Changes the model's set of custom indexes (the
- :attr:`~django.db.models.Options.index_together` option on the ``Meta``
- subclass).
- AlterOrderWithRespectTo
- -----------------------
- .. class:: AlterOrderWithRespectTo(name, order_with_respect_to)
- Makes or deletes the ``_order`` column needed for the
- :attr:`~django.db.models.Options.order_with_respect_to` option on the ``Meta``
- subclass.
- AlterModelOptions
- -----------------
- .. class:: AlterModelOptions(name, options)
- Stores changes to miscellaneous model options (settings on a model's ``Meta``)
- like ``permissions`` and ``verbose_name``. Does not affect the database, but
- persists these changes for :class:`RunPython` instances to use. ``options``
- should be a dictionary mapping option names to values.
- AlterModelManagers
- ------------------
- .. versionadded:: 1.8
- .. class:: AlterModelManagers(name, managers)
- Alters the managers that are available during migrations.
- AddField
- --------
- .. class:: AddField(model_name, name, field, preserve_default=True)
- Adds a field to a model. ``model_name`` is the model's name, ``name`` is
- the field's name, and ``field`` is an unbound Field instance (the thing
- you would put in the field declaration in ``models.py`` - for example,
- ``models.IntegerField(null=True)``.
- The ``preserve_default`` argument indicates whether the field's default
- value is permanent and should be baked into the project state (``True``),
- or if it is temporary and just for this migration (``False``) - usually
- because the migration is adding a non-nullable field to a table and needs
- a default value to put into existing rows. It does not effect the behavior
- of setting defaults in the database directly - Django never sets database
- defaults and always applies them in the Django ORM code.
- RemoveField
- -----------
- .. class:: RemoveField(model_name, name)
- Removes a field from a model.
- Bear in mind that when reversed this is actually adding a field to a model;
- if the field is not nullable this may make this operation irreversible (apart
- from any data loss, which of course is irreversible).
- AlterField
- ----------
- .. class:: AlterField(model_name, name, field, preserve_default=True)
- Alters a field's definition, including changes to its type,
- :attr:`~django.db.models.Field.null`, :attr:`~django.db.models.Field.unique`,
- :attr:`~django.db.models.Field.db_column` and other field attributes.
- The ``preserve_default`` argument indicates whether the field's default
- value is permanent and should be baked into the project state (``True``),
- or if it is temporary and just for this migration (``False``) - usually
- because the migration is altering a nullable field to a non-nullable one and
- needs a default value to put into existing rows. It does not effect the
- behavior of setting defaults in the database directly - Django never sets
- database defaults and always applies them in the Django ORM code.
- Note that not all changes are possible on all databases - for example, you
- cannot change a text-type field like ``models.TextField()`` into a number-type
- field like ``models.IntegerField()`` on most databases.
- .. versionchanged:: 1.7.1
- The ``preserve_default`` argument was added.
- RenameField
- -----------
- .. class:: RenameField(model_name, old_name, new_name)
- Changes a field's name (and, unless :attr:`~django.db.models.Field.db_column`
- is set, its column name).
- Special Operations
- ==================
- RunSQL
- ------
- .. 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
- partial indexes.
- ``sql``, and ``reverse_sql`` if provided, should be strings of SQL to run on
- the database. On most database backends (all but PostgreSQL), Django will
- split the SQL into individual statements prior to executing them. This
- requires installing the sqlparse_ Python library.
- You can also pass a list of strings or 2-tuples. The latter is used for passing
- queries and parameters in the same way as :ref:`cursor.execute()
- <executing-custom-sql>`. These three operations are equivalent::
- migrations.RunSQL("INSERT INTO musician (name) VALUES ('Reinhardt');")
- migrations.RunSQL(["INSERT INTO musician (name) VALUES ('Reinhardt');", None])
- migrations.RunSQL(["INSERT INTO musician (name) VALUES (%s);", ['Reinhardt']])
- If you want to include literal percent signs in the query, you have to double
- them if you are passing parameters.
- The ``state_operations`` argument is so you can supply operations that are
- equivalent to the SQL in terms of project state; for example, if you are
- manually creating a column, you should pass in a list containing an ``AddField``
- 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
- you don't need to double them anymore.
- .. versionchanged:: 1.8
- 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
- Pass the ``RunSQL.noop`` attribute to ``sql`` or ``reverse_sql`` when you
- want the operation not to do anything in the given direction. This is
- especially useful in making the operation reversible.
- .. _sqlparse: https://pypi.python.org/pypi/sqlparse
- RunPython
- ---------
- .. 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
- an instance of ``django.apps.registry.Apps`` containing historical models that
- 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``
- model::
- # -*- coding: utf-8 -*-
- from django.db import models, migrations
- def forwards_func(apps, schema_editor):
- # We get the model from the versioned app registry;
- # if we directly import it, it'll be the wrong version
- Country = apps.get_model("myapp", "Country")
- db_alias = schema_editor.connection.alias
- Country.objects.using(db_alias).bulk_create([
- Country(name="USA", code="us"),
- Country(name="France", code="fr"),
- ])
- class Migration(migrations.Migration):
- dependencies = []
- operations = [
- migrations.RunPython(
- forwards_func,
- ),
- ]
- This is generally the operation you would use to create
- :ref:`data migrations <data-migrations>`, run
- custom data updates and alterations, and anything else you need access to an
- ORM and/or python code for.
- If you're upgrading from South, this is basically the South pattern as an
- operation - one or two methods for forwards and backwards, with an ORM and
- schema operations available. Most of the time, you should be able to translate
- the ``orm.Model`` or ``orm["appname", "Model"]`` references from South directly
- into ``apps.get_model("appname", "Model")`` references here and leave most of
- the rest of the code unchanged for data migrations. However, ``apps`` will only
- have references to models in the current app unless migrations in other apps
- are added to the migration's dependencies.
- Much like :class:`RunSQL`, ensure that if you change schema inside here you're
- either doing it outside the scope of the Django model system (e.g. triggers)
- or that you use :class:`SeparateDatabaseAndState` to add in operations that will
- reflect your changes to the model state - otherwise, the versioned ORM and
- the autodetector will stop working correctly.
- By default, ``RunPython`` will run its contents inside a transaction even
- on databases that do not support DDL transactions (for example, MySQL and
- Oracle). This should be safe, but may cause a crash if you attempt to use
- the ``schema_editor`` provided on these backends; in this case, please
- set ``atomic=False``.
- .. warning::
- ``RunPython`` does not magically alter the connection of the models for you;
- any model methods you call will go to the default database unless you
- give them the current database alias (available from
- ``schema_editor.connection.alias``, where ``schema_editor`` is the second
- argument to your function).
- .. staticmethod:: RunPython.noop
- .. versionadded:: 1.8
- Pass the ``RunPython.noop`` method to ``code`` or ``reverse_code`` when
- you want the operation not to do anything in the given direction. This is
- especially useful in making the operation reversible.
- SeparateDatabaseAndState
- ------------------------
- .. class:: SeparateDatabaseAndState(database_operations=None, state_operations=None)
- A highly specialized operation that let you mix and match the database
- (schema-changing) and state (autodetector-powering) aspects of operations.
- It accepts two list of operations, and when asked to apply state will use the
- state list, and when asked to apply changes to the database will use the database
- list. Do not use this operation unless you're very sure you know what you're doing.
- Writing your own
- ================
- Operations have a relatively simple API, and they're designed so that you can
- easily write your own to supplement the built-in Django ones. The basic structure
- of an ``Operation`` looks like this::
- from django.db.migrations.operations.base import Operation
- class MyCustomOperation(Operation):
- # If this is False, it means that this operation will be ignored by
- # sqlmigrate; if true, it will be run and the SQL collected for its output.
- reduces_to_sql = False
- # If this is False, Django will refuse to reverse past this operation.
- reversible = False
- def __init__(self, arg1, arg2):
- # Operations are usually instantiated with arguments in migration
- # files. Store the values of them on self for later use.
- pass
- def state_forwards(self, app_label, state):
- # The Operation should take the 'state' parameter (an instance of
- # django.db.migrations.state.ProjectState) and mutate it to match
- # any schema changes that have occurred.
- pass
- def database_forwards(self, app_label, schema_editor, from_state, to_state):
- # The Operation should use schema_editor to apply any changes it
- # wants to make to the database.
- pass
- def database_backwards(self, app_label, schema_editor, from_state, to_state):
- # If reversible is True, this is called when the operation is reversed.
- pass
- def describe(self):
- # This is used to describe what the operation does in console output.
- return "Custom Operation"
- You can take this template and work from it, though we suggest looking at the
- built-in Django operations in ``django.db.migrations.operations`` - they're
- easy to read and cover a lot of the example usage of semi-internal aspects
- of the migration framework like ``ProjectState`` and the patterns used to get
- historical models.
- Some things to note:
- * You don't need to learn too much about ``ProjectState`` to just write simple
- migrations; just know that it has an ``apps`` property that gives access to
- an app registry (which you can then call ``get_model`` on).
- * ``database_forwards`` and ``database_backwards`` both get two states passed
- to them; these just represent the difference the ``state_forwards`` method
- would have applied, but are given to you for convenience and speed reasons.
- * ``to_state`` in the database_backwards method is the *older* state; that is,
- the one that will be the current state once the migration has finished reversing.
- * You might see implementations of ``references_model`` on the built-in
- operations; this is part of the autodetection code and does not matter for
- custom operations.
- As a simple example, let's make an operation that loads PostgreSQL extensions
- (which contain some of PostgreSQL's more exciting features). It's simple enough;
- there's no model state changes, and all it does is run one command::
- from django.db.migrations.operations.base import Operation
- class LoadExtension(Operation):
- reversible = True
- def __init__(self, name):
- self.name = name
- def state_forwards(self, app_label, state):
- pass
- def database_forwards(self, app_label, schema_editor, from_state, to_state):
- schema_editor.execute("CREATE EXTENSION IF NOT EXISTS %s" % self.name)
- def database_backwards(self, app_label, schema_editor, from_state, to_state):
- schema_editor.execute("DROP EXTENSION %s" % self.name)
- def describe(self):
- return "Creates extension %s" % self.name
|