迁移文件由一个或多个Operation组成,这些对象声明性地记录迁移应对数据库执行的操作。
Django还使用这些Operation对象来计算您的模型在历史上的样子,并计算自上次迁移后对模型所做的更改,以便自动编写迁移;这就是为什么他们是声明性的,因为它意味着Django可以轻松地将它们全部加载到内存中,并通过它们运行,而不用触及数据库,以确定您的项目应该是什么样子。
还有更专门的Operation对象,用于像data migrations和高级手动数据库操作。如果要封装常用的自定义更改,也可以编写自己的Operation类。
如果您需要一个空的迁移文件来写自己的Operation对象,只需使用python manage.py makemigrations - 空的 yourappname,但请注意,手动添加模式更改操作可能会混淆迁移自动检测器并导致运行makemigrations输出不正确的代码。
所有的核心Django操作都可以从django.db.migrations.operations模块获得。
有关介绍材料,请参阅migrations topic guide。
在项目历史中创建一个新模型,并在数据库中创建一个相应的表来匹配它。
name是model的名称,如写在models.py文件中。
fields是(field_name, field_instance)的2元组的列表。字段实例应为未绑定字段(因此只有models.CharField(),而不是一个字段从另一个模型)。
options是来自模型的Meta类的值的可选字典。
bases是此模型继承的其他类的可选列表;它可以包含类对象以及格式为"appname.ModelName"的字符串,如果你想依赖另一个模型(所以你从历史版本继承)。如果没有提供,它默认只继承标准的models.Model。
managers获取(manager_name, manager_instance)的2元组列表。列表中的第一个管理器将成为迁移期间此模型的默认管理器。
已添加managers参数。
将模型从旧名称重命名为新名称。
如果您立即更改模型的名称及其几个字段,则可能必须手动添加此字段;到自动检测器,这看起来像您删除了一个具有旧名称的模型,并添加了一个具有不同名称的模型,并且其创建的迁移将丢失旧表中的任何数据。
更改模型的唯一约束集(Meta子类上的unique_together选项)。
更改模型的自定义索引集(Meta子类上的index_together选项)。
在Meta子类上为order_with_respect_to选项创建或删除所需的_order列。
存储对permissions和verbose_name的杂项模型选项(模型Meta不会影响数据库,但会对RunPython实例保留这些更改以使用。options应是将选项名称映射到值的字典。
向模型中添加字段。model_name是模型的名称,name是字段的名称,field是未绑定的Field实例在models.py中 - 例如,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. 它不影响在数据库中直接设置默认值的行为 - Django从不设置数据库默认值,并始终将它们应用于Django ORM代码。
从模型中删除字段。
记住,当颠倒这实际上是添加一个字段到模型;如果字段不可为空,这可能使此操作不可逆(除了任何数据丢失,这当然是不可逆的)。
更改字段的定义,包括对其类型,null,unique,db_column和其他字段属性的更改。
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. 它不影响在数据库中直接设置默认值的行为 - Django从不设置数据库默认值,并始终将它们应用于Django ORM代码。
请注意,并非所有数据库都可以进行所有更改 - 例如,您无法更改类似models.TextField()转换为数字类型字段,如models.大多数数据库上的IntegerField()。
已添加preserve_default参数。
允许在数据库上运行任意SQL - 对于Django不能直接支持的数据库后端的更高级功能(如部分索引)非常有用。
sql和reverse_sql(如果提供)应为在数据库上运行的SQL字符串。在大多数数据库后端(除PostgreSQL之外),Django将在执行它们之前将SQL拆分为单独的语句。这需要安装sqlparse Python库。
您还可以传递字符串或2元组的列表。后者用于以与cursor.execute()相同的方式传递查询和参数。这三个操作是等效的:
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']])
如果要在查询中包括文字百分号,则必须将它们加倍(如果您正在传递参数)。
state_operations参数是这样的,您可以根据项目状态提供等同于SQL的操作;例如,如果您手动创建列,则应在此处传递包含AddField操作的列表,以便自动检测器仍然具有模型的最新状态(否则,当您下一次运行makemigrations,它将不会看到任何添加该字段的操作,因此将尝试再次运行它)。
可选的hints参数将作为**hints传递到数据库路由器的allow_migrate()方法,以帮助他们进行路由决策。有关数据库提示的更多详细信息,请参阅Hints。
如果你想在没有参数的查询中包含文字百分号,你不需要再加上它们。
添加了将参数传递到sql和reverse_sql查询的功能。
已添加hints参数。
当希望操作不在给定方向执行任何操作时,将RunSQL.noop属性传递到sql或reverse_sql。这在使操作可逆时尤其有用。
在历史上下文中运行自定义Python代码。code(和reverse_code如果提供)应该是接受两个参数的可调用对象;第一个是包含与项目历史中的操作位置匹配的历史模型的django.apps.registry.Apps的实例,第二个是SchemaEditor的实例。
可选的hints参数将作为**hints传递到数据库路由器的allow_migrate()方法,以帮助他们做出路由决策。有关数据库提示的更多详细信息,请参阅Hints。
已添加hints参数。
建议您将代码写为迁移文件中Migration类上方的单独函数,并将其传递到RunPython。这里有一个使用RunPython在Country模型上创建一些初始对象的示例:
# -*- 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,
),
]
这通常是您将用于创建data migrations,运行自定义数据更新和更改以及您需要访问ORM和/或Python代码的任何其他操作。
如果你从South升级,这基本上是南模式作为一个操作 - 一个或两个方法向前和向后,可用的ORM和模式操作。大多数情况下,您应该能够翻译orm.Model或orm [“appname”, “Model”] 引用此处的apps.get_model(“appname”, “Model”)的数据迁移的代码不变。但是,apps只会引用当前应用程序中的模型,除非将其他应用程序中的迁移添加到迁移的依赖关系中。
与RunSQL很相似,请确保如果您在此处更改模式,则可以在Django模型系统范围之外(例如,触发器)或使用SeparateDatabaseAndState添加将反映您对模型状态的更改的操作,否则版本化的ORM和自动检测器将停止正常工作。
默认情况下,RunPython将在事务中运行其内容,即使在不支持DDL事务(例如,MySQL和Oracle)的数据库上。这应该是安全的,但如果您尝试使用这些后端提供的schema_editor,可能会导致崩溃;在这种情况下,请设置atomic=False。
警告
RunPython不会神奇地改变模型的连接;您调用的任何模型方法将转到默认数据库,除非您为它们提供当前数据库别名(可从schema_editor.connection.alias获得,其中schema_editor是您的第二个参数功能)。
当希望操作在给定方向不执行任何操作时,将RunPython.noop方法传递到code或reverse_code。这在使操作可逆时尤其有用。
操作有一个相对简单的API,它们的设计使您可以轻松地编写自己的内容来补充内置的Django。Operation的基本结构如下所示:
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"
您可以使用此模板并使用它,但我们建议您查看django.db.migrations.operations中的内置Django操作 - 它们很容易阅读,并涵盖了很多示例使用像ProjectState的迁移框架的半内部方面以及用于获取历史模型的模式。
有些事情要注意:
作为一个简单的例子,让我们做一个加载PostgreSQL扩展(它包含一些PostgreSQL的更令人兴奋的功能)的操作。它很简单;没有模型状态更改,它所做的是运行一个命令:
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
2015年5月13日