Fixed #23822 -- Added support for serializing model managers in migration

Thanks to Shai Berger, Loïc Bistuer, Simon Charette, Andrew Godwin,
Tim Graham, Carl Meyer, and others for their review and input.
This commit is contained in:
Markus Holtermann 2014-12-12 23:19:58 +01:00 committed by Tim Graham
parent e37ab311fc
commit aa5ef0d4fc
28 changed files with 608 additions and 48 deletions

View file

@ -37,7 +37,7 @@ Schema Operations
CreateModel
-----------
.. class:: CreateModel(name, fields, options=None, bases=None)
.. 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.
@ -56,6 +56,14 @@ it can contain both class objects as well as strings in the format
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
-----------
@ -121,6 +129,15 @@ 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
--------

View file

@ -387,6 +387,9 @@ Migrations
* It is now possible to have migrations (most probably :ref:`data migrations
<data-migrations>`) for applications without models.
* Migrations can now :ref:`serialize model managers
<using-managers-in-migrations>` as part of the model state.
Models
^^^^^^

66
docs/topics/migrations.txt Executable file → Normal file
View file

@ -286,6 +286,36 @@ modified ``__init__`` method with the old signature. So if you need a new
argument, please create a keyword argument and add something like
``assert kwargs.get('argument_name') is not None`` in the constructor.
.. _using-managers-in-migrations:
Model managers
~~~~~~~~~~~~~~
.. versionadded:: 1.8
You can optionally serialize managers into migrations and have them available
in :class:`~django.db.migrations.operations.RunPython` operations. This is done
by defining a ``use_in_migrations`` attribute on the manager class::
class MyManager(models.Manager):
use_in_migrations = True
class MyModel(models.Model):
objects = MyManager()
If you are using the :meth:`~django.db.models.from_queryset` function to
dynamically generate a manager class, you need to inherit from the generated
class to make it importable::
class MyManager(MyBaseManager.from_queryset(CustomQuerySet)):
use_in_migrations = True
class MyModel(models.Model):
objects = MyManager()
Please refer to the notes about :ref:`historical-models` in migrations to see
the implications that come along.
Adding migrations to apps
-------------------------
@ -326,16 +356,17 @@ you can use the :djadminopt:`--name` option::
Historical models
-----------------
When you run migrations, Django is working from historical versions of
your models stored in the migration files. If you write Python code
using the :class:`~django.db.migrations.operations.RunPython` operation, or if
you have ``allow_migrate`` methods on your database routers, you will be
exposed to these versions of your models.
When you run migrations, Django is working from historical versions of your
models stored in the migration files. If you write Python code using the
:class:`~django.db.migrations.operations.RunPython` operation, or if you have
``allow_migrate`` methods on your database routers, you will be exposed to
these versions of your models.
Because it's impossible to serialize arbitrary Python code, these historical
models will not have any custom methods or managers that you have defined.
They will, however, have the same fields, relationships and ``Meta`` options
(also versioned, so they may be different from your current ones).
models will not have any custom methods that you have defined. They will,
however, have the same fields, relationships, managers (limited to those with
``use_in_migrations = True``) and ``Meta`` options (also versioned, so they may
be different from your current ones).
.. warning::
@ -344,16 +375,17 @@ They will, however, have the same fields, relationships and ``Meta`` options
constructors or instance methods. Plan appropriately!
References to functions in field options such as ``upload_to`` and
``limit_choices_to`` are serialized in migrations, so the functions will need
to be kept around for as long as there is a migration referencing them. Any
:doc:`custom model fields </howto/custom-model-fields>` will also need to be
kept, since these are imported directly by migrations.
``limit_choices_to`` and model manager declarations with managers having
``use_in_migrations = True`` are serialized in migrations, so the functions and
classes will need to be kept around for as long as there is a migration
referencing them. Any :doc:`custom model fields </howto/custom-model-fields>`
will also need to be kept, since these are imported directly by migrations.
In addition, the base classes of the model are just stored as pointers,
so you must always keep base classes around for as long as there is a migration
that contains a reference to them. On the plus side, methods and managers
from these base classes inherit normally, so if you absolutely need access
to these you can opt to move them into a superclass.
In addition, the base classes of the model are just stored as pointers, so you
must always keep base classes around for as long as there is a migration that
contains a reference to them. On the plus side, methods and managers 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: