“Django/docs/2.2.x/ref/migration-operations”的版本间差异

来自菜鸟教程
Django/docs/2.2.x/ref/migration-operations
跳转至:导航、​搜索
(autoload)
 
(Page commit)
 
第1行: 第1行:
 +
{{DISPLAYTITLE:迁移操作 — Django 文档}}
 
<div id="module-django.db.migrations.operations" class="section">
 
<div id="module-django.db.migrations.operations" class="section">
  
 
<span id="migration-operations"></span>
 
<span id="migration-operations"></span>
= Migration Operations =
+
= 迁移操作 =
  
Migration files are composed of one or more <code>Operation</code>s, objects that
+
迁移文件由一个或多个 <code>Operation</code> 组成,这些对象声明性地记录迁移应该对您的数据库执行的操作。
declaratively record what the migration should do to your database.
 
  
Django also uses these <code>Operation</code> objects to work out what your models
+
Django 还使用这些 <code>Operation</code> 对象来计算您的模型在历史上的样子,并计算自上次迁移以来您对模型所做的更改,以便它可以自动编写您的迁移; 这就是为什么它们是声明性的,因为这意味着 Django 可以轻松地将它们全部加载到内存中并在不接触数据库的情况下运行它们来计算出您的项目应该是什么样子。
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 <code>Operation</code> objects which are for things like
+
还有更专门的 <code>Operation</code> 对象,用于 [[../../topics/migrations#data-migrations|数据迁移]] 和高级手动数据库操作。 如果您想封装通常所做的自定义更改,您还可以编写自己的 <code>Operation</code> 类。
[[../../topics/migrations#data-migrations|<span class="std std-ref">data migrations</span>]] and for advanced manual database
 
manipulation. You can also write your own <code>Operation</code> classes if you want
 
to encapsulate a custom change you commonly make.
 
  
If you need an empty migration file to write your own <code>Operation</code> objects
+
如果您需要一个空的迁移文件来写入您自己的 <code>Operation</code> 对象,只需使用 <code>python manage.py makemigrations --empty yourappname</code>,但请注意,手动添加模式更改操作可能会混淆迁移自动检测器并使结果运行 [ X225X]:djadmin:`makemigrations` 输出错误的代码。
into, just use <code>python manage.py makemigrations --empty yourappname</code>,
 
but be aware that manually adding schema-altering operations can confuse the
 
migration autodetector and make resulting runs of [[../django-admin#django-admin-makemigrations|<code>makemigrations</code>]]
 
output incorrect code.
 
  
All of the core Django operations are available from the
+
所有核心 Django 操作都可以从 <code>django.db.migrations.operations</code> 模块获得。
<code>django.db.migrations.operations</code> module.
 
  
For introductory material, see the [[../../topics/migrations|<span class="doc">migrations topic guide</span>]].
+
有关介绍性材料,请参阅 [[../../topics/migrations|迁移主题指南]]
  
 
<div id="schema-operations" class="section">
 
<div id="schema-operations" class="section">
  
== Schema Operations ==
+
== 架构操作 ==
  
 
<div id="createmodel" class="section">
 
<div id="createmodel" class="section">
  
=== <code>CreateModel</code> ===
+
=== CreateModel ===
  
; ''class'' <code>CreateModel</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">fields</span>'', ''<span class="n">options</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">bases</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">managers</span><span class="o">=</span><span class="default_value">None</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#CreateModel|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">CreateModel</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">fields</span></span>'', ''<span class="n"><span class="pre">options</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">bases</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">managers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Creates a new model in the project history and a corresponding table in the
+
在项目历史中创建一个新的模型,并在数据库中创建与之匹配的相应表。
database to match it.
 
  
<code>name</code> is the model name, as would be written in the <code>models.py</code> file.
+
<code>name</code> 是型号名称,如 <code>models.py</code> 文件中所写。
  
<code>fields</code> is a list of 2-tuples of <code>(field_name, field_instance)</code>.
+
<code>fields</code> <code>(field_name, field_instance)</code> 的二元组列表。 字段实例应该是一个未绑定的字段(所以只是 <code>models.CharField(...)</code>,而不是取自另一个模型的字段)。
The field instance should be an unbound field (so just
 
<code>models.CharField(...)</code>, rather than a field taken from another model).
 
  
<code>options</code> is an optional dictionary of values from the model's <code>Meta</code> class.
+
<code>options</code> 是来自模型的 <code>Meta</code> 类的可选值字典。
  
<code>bases</code> is an optional list of other classes to have this model inherit from;
+
<code>bases</code> 是一个可选的其他类的列表,让这个模型继承; 如果您想依赖另一个模型(因此您从历史版本继承),它可以包含格式为 <code>&quot;appname.ModelName&quot;</code> 的类对象和字符串。 如果未提供,则默认为仅从标准 <code>models.Model</code> 继承。
it can contain both class objects as well as strings in the format
 
<code>&quot;appname.ModelName&quot;</code> 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 <code>models.Model</code>.
 
  
<code>managers</code> takes a list of 2-tuples of <code>(manager_name, manager_instance)</code>.
+
<code>managers</code> 获取 <code>(manager_name, manager_instance)</code> 的 2 元组列表。 列表中的第一个管理器将是迁移期间此模型的默认管理器。
The first manager in the list will be the default manager for this model during
 
migrations.
 
  
  
第66行: 第44行:
 
<div id="deletemodel" class="section">
 
<div id="deletemodel" class="section">
  
=== <code>DeleteModel</code> ===
+
=== DeleteModel ===
  
; ''class'' <code>DeleteModel</code><span class="sig-paren">(</span>''<span class="n">name</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#DeleteModel|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">DeleteModel</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Deletes the model from the project history and its table from the database.
+
从项目历史中删除模型,并从数据库中删除它的表。
  
  
第77行: 第55行:
 
<div id="renamemodel" class="section">
 
<div id="renamemodel" class="section">
  
=== <code>RenameModel</code> ===
+
=== RenameModel ===
  
; ''class'' <code>RenameModel</code><span class="sig-paren">(</span>''<span class="n">old_name</span>'', ''<span class="n">new_name</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#RenameModel|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">RenameModel</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">old_name</span></span>'', ''<span class="n"><span class="pre">new_name</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
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.
 
  
  
第94行: 第68行:
 
<div id="altermodeltable" class="section">
 
<div id="altermodeltable" class="section">
  
=== <code>AlterModelTable</code> ===
+
=== AlterModelTable ===
  
; ''class'' <code>AlterModelTable</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">table</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#AlterModelTable|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AlterModelTable</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">table</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Changes the model's table name (the [[../models/options#django.db.models.Options|<code>db_table</code>]]
+
更改模型的表名(<code>Meta</code> 子类上的 [[../models/options#django.db.models.Options|db_table]] 选项)。
option on the <code>Meta</code> subclass).
 
  
  
第106行: 第79行:
 
<div id="alteruniquetogether" class="section">
 
<div id="alteruniquetogether" class="section">
  
=== <code>AlterUniqueTogether</code> ===
+
=== AlterUniqueTogether ===
  
; ''class'' <code>AlterUniqueTogether</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">unique_together</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#AlterUniqueTogether|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AlterUniqueTogether</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">unique_together</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Changes the model's set of unique constraints (the
+
更改模型的唯一约束集(<code>Meta</code> 子类上的 [[../models/options#django.db.models.Options|unique_together]] 选项)。
[[../models/options#django.db.models.Options|<code>unique_together</code>]] option on the <code>Meta</code>
 
subclass).
 
  
  
第119行: 第90行:
 
<div id="alterindextogether" class="section">
 
<div id="alterindextogether" class="section">
  
=== <code>AlterIndexTogether</code> ===
+
=== AlterIndexTogether ===
  
; ''class'' <code>AlterIndexTogether</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">index_together</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#AlterIndexTogether|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AlterIndexTogether</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">index_together</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Changes the model's set of custom indexes (the
+
更改模型的自定义索引集(<code>Meta</code> 子类上的 [[../models/options#django.db.models.Options|index_together]] 选项)。
[[../models/options#django.db.models.Options|<code>index_together</code>]] option on the <code>Meta</code>
 
subclass).
 
  
  
第132行: 第101行:
 
<div id="alterorderwithrespectto" class="section">
 
<div id="alterorderwithrespectto" class="section">
  
=== <code>AlterOrderWithRespectTo</code> ===
+
=== AlterOrderWithRespectTo ===
  
; ''class'' <code>AlterOrderWithRespectTo</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">order_with_respect_to</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#AlterOrderWithRespectTo|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AlterOrderWithRespectTo</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">order_with_respect_to</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Makes or deletes the <code>_order</code> column needed for the
+
创建或删除 <code>Meta</code> 子类上的 [[../models/options#django.db.models.Options|order_with_respect_to]] 选项所需的 <code>_order</code> 列。
[[../models/options#django.db.models.Options|<code>order_with_respect_to</code>]] option on the <code>Meta</code>
 
subclass.
 
  
  
第145行: 第112行:
 
<div id="altermodeloptions" class="section">
 
<div id="altermodeloptions" class="section">
  
=== <code>AlterModelOptions</code> ===
+
=== AlterModelOptions ===
  
; ''class'' <code>AlterModelOptions</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">options</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#AlterModelOptions|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AlterModelOptions</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">options</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Stores changes to miscellaneous model options (settings on a model's <code>Meta</code>)
+
存储对其他模型选项(模型 <code>Meta</code> 上的设置)的更改,例如 <code>permissions</code> <code>verbose_name</code>。 不会影响数据库,但会保留这些更改以供 [[#django.db.migrations.operations.RunPython|RunPython]] 实例使用。 <code>options</code> 应该是将选项名称映射到值的字典。
like <code>permissions</code> and <code>verbose_name</code>. Does not affect the database, but
 
persists these changes for [[#django.db.migrations.operations.RunPython|<code>RunPython</code>]] instances to use. <code>options</code>
 
should be a dictionary mapping option names to values.
 
  
  
第159行: 第123行:
 
<div id="altermodelmanagers" class="section">
 
<div id="altermodelmanagers" class="section">
  
=== <code>AlterModelManagers</code> ===
+
=== AlterModelManagers ===
  
; ''class'' <code>AlterModelManagers</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">managers</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#AlterModelManagers|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AlterModelManagers</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">managers</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Alters the managers that are available during migrations.
+
改变迁移期间可用的管理器。
  
  
第170行: 第134行:
 
<div id="addfield" class="section">
 
<div id="addfield" class="section">
  
=== <code>AddField</code> ===
+
=== AddField ===
  
; ''class'' <code>AddField</code><span class="sig-paren">(</span>''<span class="n">model_name</span>'', ''<span class="n">name</span>'', ''<span class="n">field</span>'', ''<span class="n">preserve_default</span><span class="o">=</span><span class="default_value">True</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/fields.html#AddField|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AddField</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">model_name</span></span>'', ''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">field</span></span>'', ''<span class="n"><span class="pre">preserve_default</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Adds a field to a model. <code>model_name</code> is the model's name, <code>name</code> is
+
向模型添加字段。 <code>model_name</code> 是模型的名称,<code>name</code> 是字段的名称,<code>field</code> 是一个未绑定的 Field 实例(你会在 [X162X ] - 例如,<code>models.IntegerField(null=True)</code>
the field's name, and <code>field</code> is an unbound Field instance (the thing
 
you would put in the field declaration in <code>models.py</code> - for example,
 
<code>models.IntegerField(null=True)</code>.
 
  
The <code>preserve_default</code> argument indicates whether the field's default
+
<code>preserve_default</code> 参数表示该字段的默认值是否是永久的并且应该被烘焙到项目状态 (<code>True</code>),或者它是否是临时的并且仅用于此迁移 (<code>False</code> ) - 通常是因为迁移正在向表中添加不可为空的字段,并且需要将默认值放入现有行中。 它不会直接影响在数据库中设置默认值的行为 - Django 从不设置数据库默认值,而是始终将它们应用到 Django ORM 代码中。
value is permanent and should be baked into the project state (<code>True</code>),
 
or if it is temporary and just for this migration (<code>False</code>) - 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 affect the behavior
 
of setting defaults in the database directly - Django never sets database
 
defaults and always applies them in the Django ORM code.
 
  
 
<div class="admonition warning">
 
<div class="admonition warning">
第192行: 第147行:
 
警告
 
警告
  
On older databases, adding a field with a default value may cause a full
+
在较旧的数据库上,添加具有默认值的字段可能会导致表的完全重写。 即使对于可为空的字段也会发生这种情况,并且可能会对性能产生负面影响。 为避免这种情况,应采取以下步骤。
rewrite of the table. This happens even for nullable fields and may have a
 
negative performance impact. To avoid that, the following steps should be
 
taken.
 
  
* Add the nullable field without the default value and run the [[../django-admin#django-admin-makemigrations|<code>makemigrations</code>]] command. This should generate a migration with an <code>AddField</code> operation.
+
* 添加没有默认值的可空字段并运行 [[#id3|:djadmin:`makemigrations`]] 命令。 这应该会生成一个带有 <code>AddField</code> 操作的迁移。
* Add the default value to your field and run the [[../django-admin#django-admin-makemigrations|<code>makemigrations</code>]] command. This should generate a migration with an <code>AlterField</code> operation.
+
* 将默认值添加到您的字段并运行 [[#id5|:djadmin:`makemigrations`]] 命令。 这应该会生成一个带有 <code>AlterField</code> 操作的迁移。
  
  
第206行: 第158行:
 
<div id="removefield" class="section">
 
<div id="removefield" class="section">
  
=== <code>RemoveField</code> ===
+
=== RemoveField ===
  
; ''class'' <code>RemoveField</code><span class="sig-paren">(</span>''<span class="n">model_name</span>'', ''<span class="n">name</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/fields.html#RemoveField|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">RemoveField</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">model_name</span></span>'', ''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Removes a field from a model.
+
从模型中删除一个字段。
  
Bear in mind that when reversed, this is actually adding a field to a model.
+
请记住,当相反时,这实际上是向模型添加一个字段。 如果该字段可以为空或者它具有可用于填充重新创建的列的默认值,则该操作是可逆的(除了任何数据丢失,这当然是不可逆的)。 如果该字段不可为空且没有默认值,则该操作是不可逆的。
The operation is reversible (apart from any data loss, which of course is
 
irreversible) if the field is nullable or if it has a default value that can be
 
used to populate the recreated column. If the field is not nullable and does
 
not have a default value, the operation is irreversible.
 
  
  
第223行: 第171行:
 
<div id="alterfield" class="section">
 
<div id="alterfield" class="section">
  
=== <code>AlterField</code> ===
+
=== AlterField ===
  
; ''class'' <code>AlterField</code><span class="sig-paren">(</span>''<span class="n">model_name</span>'', ''<span class="n">name</span>'', ''<span class="n">field</span>'', ''<span class="n">preserve_default</span><span class="o">=</span><span class="default_value">True</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/fields.html#AlterField|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AlterField</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">model_name</span></span>'', ''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">field</span></span>'', ''<span class="n"><span class="pre">preserve_default</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Alters a field's definition, including changes to its type,
+
更改字段的定义,包括更改其类型、[[../models/fields#django.db.models.Field|null]][[../models/fields#django.db.models.Field|unique]][[../models/fields#django.db.models.Field|db_column]] 和其他字段属性。
[[../models/fields#django.db.models.Field|<code>null</code>]], [[../models/fields#django.db.models.Field|<code>unique</code>]],
 
[[../models/fields#django.db.models.Field|<code>db_column</code>]] and other field attributes.
 
  
The <code>preserve_default</code> argument indicates whether the field's default
+
<code>preserve_default</code> 参数表示该字段的默认值是否是永久的并且应该被烘焙到项目状态 (<code>True</code>),或者它是否是临时的并且仅用于此迁移 (<code>False</code> ) - 通常是因为迁移将可空字段更改为不可空字段,并且需要将默认值放入现有行。 它不会直接影响在数据库中设置默认值的行为 - Django 从不设置数据库默认值,而是始终将它们应用到 Django ORM 代码中。
value is permanent and should be baked into the project state (<code>True</code>),
 
or if it is temporary and just for this migration (<code>False</code>) - 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 affect 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
+
请注意,并非所有数据库都可以进行所有更改 - 例如,在大多数数据库上,您不能将 <code>models.TextField()</code> 之类的文本类型字段更改为 <code>models.IntegerField()</code> 之类的数字类型字段。
cannot change a text-type field like <code>models.TextField()</code> into a number-type
 
field like <code>models.IntegerField()</code> on most databases.
 
  
  
第248行: 第186行:
 
<div id="renamefield" class="section">
 
<div id="renamefield" class="section">
  
=== <code>RenameField</code> ===
+
=== RenameField ===
  
; ''class'' <code>RenameField</code><span class="sig-paren">(</span>''<span class="n">model_name</span>'', ''<span class="n">old_name</span>'', ''<span class="n">new_name</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/fields.html#RenameField|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">RenameField</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">model_name</span></span>'', ''<span class="n"><span class="pre">old_name</span></span>'', ''<span class="n"><span class="pre">new_name</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Changes a field's name (and, unless [[../models/fields#django.db.models.Field|<code>db_column</code>]]
+
更改字段的名称(并且,除非设置了 [[../models/fields#django.db.models.Field|db_column]],则更改其列名称)。
is set, its column name).
 
  
  
第260行: 第197行:
 
<div id="addindex" class="section">
 
<div id="addindex" class="section">
  
=== <code>AddIndex</code> ===
+
=== AddIndex ===
  
; ''class'' <code>AddIndex</code><span class="sig-paren">(</span>''<span class="n">model_name</span>'', ''<span class="n">index</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#AddIndex|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AddIndex</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">model_name</span></span>'', ''<span class="n"><span class="pre">index</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Creates an index in the database table for the model with <code>model_name</code>.
+
在数据库表中为具有 <code>model_name</code> 的模型创建索引。 <code>index</code> [[../models/indexes#django.db.models|Index]] 类的一个实例。
<code>index</code> is an instance of the [[../models/indexes#django.db.models|<code>Index</code>]] class.
 
  
  
第272行: 第208行:
 
<div id="removeindex" class="section">
 
<div id="removeindex" class="section">
  
=== <code>RemoveIndex</code> ===
+
=== RemoveIndex ===
  
; ''class'' <code>RemoveIndex</code><span class="sig-paren">(</span>''<span class="n">model_name</span>'', ''<span class="n">name</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#RemoveIndex|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">RemoveIndex</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">model_name</span></span>'', ''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Removes the index named <code>name</code> from the model with <code>model_name</code>.
+
从带有 <code>model_name</code> 的模型中删除名为 <code>name</code> 的索引。
  
  
第283行: 第219行:
 
<div id="addconstraint" class="section">
 
<div id="addconstraint" class="section">
  
=== <code>AddConstraint</code> ===
+
=== AddConstraint ===
  
; ''class'' <code>AddConstraint</code><span class="sig-paren">(</span>''<span class="n">model_name</span>'', ''<span class="n">constraint</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#AddConstraint|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">AddConstraint</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">model_name</span></span>'', ''<span class="n"><span class="pre">constraint</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
 
<div class="versionadded">
 
<div class="versionadded">
  
 +
<span class="versionmodified added">2.2 版中的新功能。</span>
  
  
 
</div>
 
</div>
Creates a [[../models/constraints|<span class="doc">constraint</span>]] in the database table for
+
在数据库表中为具有 <code>model_name</code> 的模型创建 [[../models/constraints|约束]]
the model with <code>model_name</code>.
 
  
  
第300行: 第236行:
 
<div id="removeconstraint" class="section">
 
<div id="removeconstraint" class="section">
  
=== <code>RemoveConstraint</code> ===
+
=== RemoveConstraint ===
  
; ''class'' <code>RemoveConstraint</code><span class="sig-paren">(</span>''<span class="n">model_name</span>'', ''<span class="n">name</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/models.html#RemoveConstraint|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">RemoveConstraint</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">model_name</span></span>'', ''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
 
<div class="versionadded">
 
<div class="versionadded">
  
 +
<span class="versionmodified added">2.2 版中的新功能。</span>
  
  
 
</div>
 
</div>
Removes the constraint named <code>name</code> from the model with <code>model_name</code>.
+
从具有 <code>model_name</code> 的模型中移除名为 <code>name</code> 的约束。
  
  
第318行: 第255行:
 
<div id="special-operations" class="section">
 
<div id="special-operations" class="section">
  
== Special Operations ==
+
== 特殊操作 ==
  
 
<div id="runsql" class="section">
 
<div id="runsql" class="section">
  
=== <code>RunSQL</code> ===
+
=== RunSQL ===
  
; ''class'' <code>RunSQL</code><span class="sig-paren">(</span>''<span class="n">sql</span>'', ''<span class="n">reverse_sql</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">state_operations</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">hints</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">elidable</span><span class="o">=</span><span class="default_value">False</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/special.html#RunSQL|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">RunSQL</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">sql</span></span>'', ''<span class="n"><span class="pre">reverse_sql</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">state_operations</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">hints</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">elidable</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Allows running of arbitrary SQL on the database - useful for more advanced
+
允许在数据库上运行任意 SQL - 对于 Django 不直接支持的数据库后端的更高级功能非常有用,例如部分索引。
features of database backends that Django doesn't support directly, like
 
partial indexes.
 
  
<code>sql</code>, and <code>reverse_sql</code> if provided, should be strings of SQL to run on
+
<code>sql</code> <code>reverse_sql</code>(如果提供)应该是在数据库上运行的 SQL 字符串。 在大多数数据库后端(除了 PostgreSQL 之外),Django 会在执行之前将 SQL 拆分为单独的语句。
the database. On most database backends (all but PostgreSQL), Django will
 
split the SQL into individual statements prior to executing them.
 
  
You can also pass a list of strings or 2-tuples. The latter is used for passing
+
您还可以传递字符串列表或 2 元组。 后者用于以与 [[../../topics/db/sql#executing-custom-sql|cursor.execute()]] 相同的方式传递查询和参数。 这三个操作是等价的:
queries and parameters in the same way as [[../../topics/db/sql#executing-custom-sql|<span class="std std-ref">cursor.execute()</span>]]. These three operations are equivalent:
 
  
 
<div class="highlight-default notranslate">
 
<div class="highlight-default notranslate">
第342行: 第274行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>migrations.RunSQL(&quot;INSERT INTO musician (name) VALUES ('Reinhardt');&quot;)
+
<syntaxhighlight lang="python">migrations.RunSQL("INSERT INTO musician (name) VALUES ('Reinhardt');")
migrations.RunSQL([(&quot;INSERT INTO musician (name) VALUES ('Reinhardt');&quot;, None)])
+
migrations.RunSQL([("INSERT INTO musician (name) VALUES ('Reinhardt');", None)])
migrations.RunSQL([(&quot;INSERT INTO musician (name) VALUES (%s);&quot;, ['Reinhardt'])])</pre>
+
migrations.RunSQL([("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])])</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
If you want to include literal percent signs in the query, you have to double
+
如果你想在查询中包含字面的百分号,如果你传递的是参数,你必须将它们翻倍。
them if you are passing parameters.
 
  
The <code>reverse_sql</code> queries are executed when the migration is unapplied, so
+
<code>reverse_sql</code> 查询在未应用迁移时执行,因此您可以撤消在转发查询中所做的更改:
you can reverse the changes done in the forwards queries:
 
  
 
<div class="highlight-default notranslate">
 
<div class="highlight-default notranslate">
第359行: 第289行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>migrations.RunSQL(
+
<syntaxhighlight lang="python">migrations.RunSQL(
     [(&quot;INSERT INTO musician (name) VALUES (%s);&quot;, ['Reinhardt'])],
+
     [("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])],
     [(&quot;DELETE FROM musician where name=%s;&quot;, ['Reinhardt'])],
+
     [("DELETE FROM musician where name=%s;", ['Reinhardt'])],
)</pre>
+
)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The <code>state_operations</code> argument is so you can supply operations that are
+
<code>state_operations</code> 参数使您可以提供在项目状态方面与 SQL 等效的操作; 例如,如果您手动创建列,则应在此处传入包含 <code>AddField</code> 操作的列表,以便自动检测器仍具有模型的最新状态(否则,当您下次运行时<code>makemigrations</code>,它不会看到任何添加该字段的操作,因此将尝试再次运行它)。 例如:
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 <code>AddField</code>
 
operation here so that the autodetector still has an up-to-date state of the
 
model (otherwise, when you next run <code>makemigrations</code>, it won't see any
 
operation that adds that field and so will try to run it again). For example:
 
  
 
<div class="highlight-default notranslate">
 
<div class="highlight-default notranslate">
第378行: 第303行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>migrations.RunSQL(
+
<syntaxhighlight lang="python">migrations.RunSQL(
     &quot;ALTER TABLE musician ADD COLUMN name varchar(255) NOT NULL;&quot;,
+
     "ALTER TABLE musician ADD COLUMN name varchar(255) NOT NULL;",
 
     state_operations=[
 
     state_operations=[
 
         migrations.AddField(
 
         migrations.AddField(
第387行: 第312行:
 
         ),
 
         ),
 
     ],
 
     ],
)</pre>
+
)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The optional <code>hints</code> argument will be passed as <code>**hints</code> to the
+
可选的 <code>hints</code> 参数将作为 <code>**hints</code> 传递给数据库路由器的 [[../../topics/db/multi-db#allow_migrate|allow_migrate()]] 方法,以帮助它们做出路由决策。 有关数据库提示的更多详细信息,请参阅 [[../../topics/db/multi-db#topics-db-multi-db-hints|Hints]]
[[../../topics/db/multi-db#allow_migrate|<code>allow_migrate()</code>]] method of database routers to assist them in making
 
routing decisions. See [[../../topics/db/multi-db#topics-db-multi-db-hints|<span class="std std-ref">提示</span>]] for more details on
 
database hints.
 
  
The optional <code>elidable</code> argument determines whether or not the operation will
+
可选的 <code>elidable</code> 参数确定在 [[../../topics/migrations#migration-squashing|挤压迁移]] 时是否删除(省略)该操作。
be removed (elided) when [[../../topics/migrations#migration-squashing|<span class="std std-ref">squashing migrations</span>]].
 
  
; <code>RunSQL.</code><code>noop</code>
+
; <span class="sig-prename descclassname"><span class="pre">RunSQL.</span></span><span class="sig-name descname"><span class="pre">noop</span></span>
: Pass the <code>RunSQL.noop</code> attribute to <code>sql</code> or <code>reverse_sql</code> when you want the operation not to do anything in the given direction. This is especially useful in making the operation reversible.
+
: 当您希望操作不在给定方向上执行任何操作时,将 <code>RunSQL.noop</code> 属性传递给 <code>sql</code> <code>reverse_sql</code>。 这在使操作可逆时特别有用。
  
  
第407行: 第328行:
 
<div id="runpython" class="section">
 
<div id="runpython" class="section">
  
=== <code>RunPython</code> ===
+
=== RunPython ===
  
; ''class'' <code>RunPython</code><span class="sig-paren">(</span>''<span class="n">code</span>'', ''<span class="n">reverse_code</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">atomic</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">hints</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">elidable</span><span class="o">=</span><span class="default_value">False</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/special.html#RunPython|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">RunPython</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">code</span></span>'', ''<span class="n"><span class="pre">reverse_code</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">atomic</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">hints</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">elidable</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
Runs custom Python code in a historical context. <code>code</code> (and <code>reverse_code</code>
+
在历史上下文中运行自定义 Python 代码。 <code>code</code>(和 <code>reverse_code</code> 如果提供)应该是接受两个参数的可调用对象; 第一个是 <code>django.apps.registry.Apps</code> 的实例,其中包含与操作在项目历史中的位置相匹配的历史模型,第二个是 [[../schema-editor#django.db.backends.base.schema|SchemaEditor]] 的实例。
if supplied) should be callable objects that accept two arguments; the first is
 
an instance of <code>django.apps.registry.Apps</code> containing historical models that
 
match the operation's place in the project history, and the second is an
 
instance of [[../schema-editor#django.db.backends.base.schema|<code>SchemaEditor</code>]].
 
  
The <code>reverse_code</code> argument is called when unapplying migrations. This
+
<code>reverse_code</code> 参数在取消应用迁移时被调用。 这个 callable 应该撤消在 <code>code</code> callable 中所做的事情,以便迁移是可逆的。
callable should undo what is done in the <code>code</code> callable so that the
 
migration is reversible.
 
  
The optional <code>hints</code> argument will be passed as <code>**hints</code> to the
+
可选的 <code>hints</code> 参数将作为 <code>**hints</code> 传递给数据库路由器的 [[../../topics/db/multi-db#allow_migrate|allow_migrate()]] 方法,以帮助它们做出路由决策。 有关数据库提示的更多详细信息,请参阅 [[../../topics/db/multi-db#topics-db-multi-db-hints|Hints]]
[[../../topics/db/multi-db#allow_migrate|<code>allow_migrate()</code>]] method of database routers to assist them in making a
 
routing decision. See [[../../topics/db/multi-db#topics-db-multi-db-hints|<span class="std std-ref">提示</span>]] for more details on
 
database hints.
 
  
The optional <code>elidable</code> argument determines whether or not the operation will
+
可选的 <code>elidable</code> 参数确定在 [[../../topics/migrations#migration-squashing|挤压迁移]] 时是否删除(省略)该操作。
be removed (elided) when [[../../topics/migrations#migration-squashing|<span class="std std-ref">squashing migrations</span>]].
 
  
You are advised to write the code as a separate function above the <code>Migration</code>
+
建议将代码写成迁移文件中<code>Migration</code>类上面的单独函数,直接传给<code>RunPython</code>即可。 下面是使用 <code>RunPython</code> <code>Country</code> 模型上创建一些初始对象的示例:
class in the migration file, and just pass it to <code>RunPython</code>. Here's an
 
example of using <code>RunPython</code> to create some initial objects on a <code>Country</code>
 
model:
 
  
 
<div class="highlight-default notranslate">
 
<div class="highlight-default notranslate">
第439行: 第347行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>from django.db import migrations
+
<syntaxhighlight lang="python">from django.db import migrations
  
 
def forwards_func(apps, schema_editor):
 
def forwards_func(apps, schema_editor):
 
     # We get the model from the versioned app registry;
 
     # We get the model from the versioned app registry;
 
     # if we directly import it, it'll be the wrong version
 
     # if we directly import it, it'll be the wrong version
     Country = apps.get_model(&quot;myapp&quot;, &quot;Country&quot;)
+
     Country = apps.get_model("myapp", "Country")
 
     db_alias = schema_editor.connection.alias
 
     db_alias = schema_editor.connection.alias
 
     Country.objects.using(db_alias).bulk_create([
 
     Country.objects.using(db_alias).bulk_create([
         Country(name=&quot;USA&quot;, code=&quot;us&quot;),
+
         Country(name="USA", code="us"),
         Country(name=&quot;France&quot;, code=&quot;fr&quot;),
+
         Country(name="France", code="fr"),
 
     ])
 
     ])
  
第454行: 第362行:
 
     # forwards_func() creates two Country instances,
 
     # forwards_func() creates two Country instances,
 
     # so reverse_func() should delete them.
 
     # so reverse_func() should delete them.
     Country = apps.get_model(&quot;myapp&quot;, &quot;Country&quot;)
+
     Country = apps.get_model("myapp", "Country")
 
     db_alias = schema_editor.connection.alias
 
     db_alias = schema_editor.connection.alias
     Country.objects.using(db_alias).filter(name=&quot;USA&quot;, code=&quot;us&quot;).delete()
+
     Country.objects.using(db_alias).filter(name="USA", code="us").delete()
     Country.objects.using(db_alias).filter(name=&quot;France&quot;, code=&quot;fr&quot;).delete()
+
     Country.objects.using(db_alias).filter(name="France", code="fr").delete()
  
 
class Migration(migrations.Migration):
 
class Migration(migrations.Migration):
第465行: 第373行:
 
     operations = [
 
     operations = [
 
         migrations.RunPython(forwards_func, reverse_func),
 
         migrations.RunPython(forwards_func, reverse_func),
     ]</pre>
+
     ]</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This is generally the operation you would use to create
+
这通常是您用于创建 [[../../topics/migrations#data-migrations|数据迁移]] 、运行自定义数据更新和更改以及您需要访问 ORM /Python 代码的任何其他操作的操作。
[[../../topics/migrations#data-migrations|<span class="std std-ref">data migrations</span>]], 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
+
如果您是从 South 升级,这基本上是作为操作的 South 模式 - 一种或两种向前和向后的方法,以及可用的 ORM 和模式操作。 大多数情况下,您应该能够将来自 South 的 <code>orm.Model</code> <code>orm[&quot;appname&quot;, &quot;Model&quot;]</code> 引用直接转换为 <code>apps.get_model(&quot;appname&quot;, &quot;Model&quot;)</code> 引用,并保留大部分其余代码的数据不变迁移。 但是,<code>apps</code> 将只引用当前应用程序中的模型,除非其他应用程序中的迁移被添加到迁移的依赖项中。
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 <code>orm.Model</code> or <code>orm[&quot;appname&quot;, &quot;Model&quot;]</code> references from South directly
 
into <code>apps.get_model(&quot;appname&quot;, &quot;Model&quot;)</code> references here and leave most of
 
the rest of the code unchanged for data migrations. However, <code>apps</code> will only
 
have references to models in the current app unless migrations in other apps
 
are added to the migration's dependencies.
 
  
Much like [[#django.db.migrations.operations.RunSQL|<code>RunSQL</code>]], ensure that if you change schema inside here you're
+
很像 [[#django.db.migrations.operations.RunSQL|RunSQL]],确保如果你在这里改变架构,你要么在 Django 模型系统的范围之外做它(例如 触发器) 或者您使用 [[#django.db.migrations.operations.SeparateDatabaseAndState|SeparateDatabaseAndState]] 添加将反映您对模型状态更改的操作 - 否则,版本化 ORM 和自动检测器将停止正常工作。
either doing it outside the scope of the Django model system (e.g. triggers)
 
or that you use [[#django.db.migrations.operations.SeparateDatabaseAndState|<code>SeparateDatabaseAndState</code>]] 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, <code>RunPython</code> will run its contents inside a transaction on
+
默认情况下,<code>RunPython</code> 将在不支持 DDL 事务的数据库(例如 MySQL 和 Oracle)上的事务中运行其内容。 这应该是安全的,但如果您尝试使用这些后端提供的 <code>schema_editor</code>,可能会导致崩溃; 在这种情况下,将 <code>atomic=False</code> 传递给 <code>RunPython</code> 操作。
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 <code>schema_editor</code> provided on these backends; in this case, pass
 
<code>atomic=False</code> to the <code>RunPython</code> operation.
 
  
On databases that do support DDL transactions (SQLite and PostgreSQL),
+
在支持 DDL 事务(SQLite 和 PostgreSQL)的数据库上,除了为每次迁移创建的事务之外,<code>RunPython</code> 操作不会自动添加任何事务。 因此,例如,在 PostgreSQL 上,您应该避免在同一迁移中组合架构更改和 <code>RunPython</code> 操作,否则您可能会遇到类似 <code>OperationalError: cannot ALTER TABLE &quot;mytable&quot; because it has pending trigger events</code> 的错误。
<code>RunPython</code> operations do not have any transactions automatically added
 
besides the transactions created for each migration. Thus, on PostgreSQL, for
 
example, you should avoid combining schema changes and <code>RunPython</code> operations
 
in the same migration or you may hit errors like <code>OperationalError: cannot ALTER TABLE &quot;mytable&quot; because it has pending trigger events</code>.
 
  
If you have a different database and aren't sure if it supports DDL
+
如果您有不同的数据库并且不确定它是否支持 DDL 事务,请检查 <code>django.db.connection.features.can_rollback_ddl</code> 属性。
transactions, check the <code>django.db.connection.features.can_rollback_ddl</code>
 
attribute.
 
  
If the <code>RunPython</code> operation is part of a [[../../howto/writing-migrations#non-atomic-migrations|<span class="std std-ref">non-atomic migration</span>]], the operation will only be executed in a transaction
+
如果 <code>RunPython</code> 操作是 [[../../howto/writing-migrations#non-atomic-migrations|非原子迁移]] 的一部分,则只有将 <code>atomic=True</code> 传递给 <code>RunPython</code>,该操作才会在事务中执行手术。
if <code>atomic=True</code> is passed to the <code>RunPython</code> operation.
 
  
 
<div class="admonition warning">
 
<div class="admonition warning">
第513行: 第396行:
 
警告
 
警告
  
<code>RunPython</code> does not magically alter the connection of the models for you;
+
<code>RunPython</code> 不会为你神奇地改变模型的连接; 您调用的任何模型方法都将转到默认数据库,除非您为它们提供当前数据库别名(可从 <code>schema_editor.connection.alias</code> 获得,其中 <code>schema_editor</code> 是您函数的第二个参数)。
any model methods you call will go to the default database unless you
 
give them the current database alias (available from
 
<code>schema_editor.connection.alias</code>, where <code>schema_editor</code> is the second
 
argument to your function).
 
  
  
 
</div>
 
</div>
; ''static'' <code>RunPython.</code><code>noop</code><span class="sig-paren">(</span><span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/special.html#RunPython.noop|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">static</span>'' <span class="sig-prename descclassname"><span class="pre">RunPython.</span></span><span class="sig-name descname"><span class="pre">noop</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span>
: Pass the <code>RunPython.noop</code> method to <code>code</code> or <code>reverse_code</code> when you want the operation not to do anything in the given direction. This is especially useful in making the operation reversible.
+
: 当您希望操作在给定方向上不执行任何操作时,将 <code>RunPython.noop</code> 方法传递给 <code>code</code> <code>reverse_code</code>。 这在使操作可逆时特别有用。
  
  
第528行: 第407行:
 
<div id="separatedatabaseandstate" class="section">
 
<div id="separatedatabaseandstate" class="section">
  
=== <code>SeparateDatabaseAndState</code> ===
+
=== SeparateDatabaseAndState ===
  
; ''class'' <code>SeparateDatabaseAndState</code><span class="sig-paren">(</span>''<span class="n">database_operations</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">state_operations</span><span class="o">=</span><span class="default_value">None</span>''<span class="sig-paren">)</span>[[../_modules/django/db/migrations/operations/special.html#SeparateDatabaseAndState|<span class="viewcode-link">[源代码]</span>]]
+
; ''<span class="pre">class</span>'' <span class="sig-name descname"><span class="pre">SeparateDatabaseAndState</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">database_operations</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">state_operations</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span>
 
:  
 
:  
  
A highly specialized operation that let you mix and match the database
+
一个高度专业化的操作,让你混合和匹配数据库(架构改变)和状态(自动检测器支持)方面的操作。
(schema-changing) and state (autodetector-powering) aspects of operations.
 
  
It accepts two lists 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.
 
  
  
第547行: 第423行:
  
 
<span id="writing-your-own-migration-operation"></span>
 
<span id="writing-your-own-migration-operation"></span>
== Writing your own ==
+
== 自己写 ==
  
Operations have a relatively simple API, and they're designed so that you can
+
操作有一个相对简单的 API,它们的设计使您可以轻松地编写自己的 API 来补充内置的 Django API。 <code>Operation</code> 的基本结构如下所示:
easily write your own to supplement the built-in Django ones. The basic structure
 
of an <code>Operation</code> looks like this:
 
  
 
<div class="highlight-default notranslate">
 
<div class="highlight-default notranslate">
第557行: 第431行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>from django.db.migrations.operations.base import Operation
+
<syntaxhighlight lang="python">from django.db.migrations.operations.base import Operation
  
 
class MyCustomOperation(Operation):
 
class MyCustomOperation(Operation):
第590行: 第464行:
 
     def describe(self):
 
     def describe(self):
 
         # This is used to describe what the operation does in console output.
 
         # This is used to describe what the operation does in console output.
         return &quot;Custom Operation&quot;</pre>
+
         return "Custom Operation"</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
You can take this template and work from it, though we suggest looking at the
+
您可以使用此模板并从中工作,但我们建议查看 <code>django.db.migrations.operations</code> 中的内置 Django 操作 - 它们易于阅读并涵盖了许多半内部方面的示例用法迁移框架,如 <code>ProjectState</code> 和用于获取历史模型的模式,以及 <code>ModelState</code> 和用于改变 <code>state_forwards()</code> 中的历史模型的模式。
built-in Django operations in <code>django.db.migrations.operations</code> - they're
 
easy to read and cover a lot of the example usage of semi-internal aspects
 
of the migration framework like <code>ProjectState</code> and the patterns used to get
 
historical models, as well as <code>ModelState</code> and the patterns used to mutate
 
historical models in <code>state_forwards()</code>.
 
  
Some things to note:
+
注意事项:
  
 
<ul>
 
<ul>
<li><p>You don't need to learn too much about <code>ProjectState</code> to just write simple
+
<li><p>你不需要学习太多 <code>ProjectState</code> 来编写简单的迁移; 只知道它有一个 <code>apps</code> 属性,可以访问应用程序注册表(然后您可以调用 <code>get_model</code>)。</p></li>
migrations; just know that it has an <code>apps</code> property that gives access to
+
<li><p><code>database_forwards</code> <code>database_backwards</code> 都得到两个传递给它们的状态; 这些仅代表 <code>state_forwards</code> 方法将应用的差异,但出于方便和速度的原因提供给您。</p></li>
an app registry (which you can then call <code>get_model</code> on).</p></li>
+
<li><p>如果要使用 <code>database_forwards()</code> <code>database_backwards()</code> 中的 <code>from_state</code> 参数中的模型类或模型实例,则必须使用 <code>clear_delayed_apps_cache()</code> 方法渲染模型状态以提供相关模型:</p>
<li><p><code>database_forwards</code> and <code>database_backwards</code> both get two states passed
 
to them; these just represent the difference the <code>state_forwards</code> method
 
would have applied, but are given to you for convenience and speed reasons.</p></li>
 
<li><p>If you want to work with model classes or model instances from the
 
<code>from_state</code> argument in <code>database_forwards()</code> or
 
<code>database_backwards()</code>, you must render model states using the
 
<code>clear_delayed_apps_cache()</code> method to make related models available:</p>
 
 
<div class="highlight-default notranslate">
 
<div class="highlight-default notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def database_forwards(self, app_label, schema_editor, from_state, to_state):
+
<syntaxhighlight lang="python">def database_forwards(self, app_label, schema_editor, from_state, to_state):
 
     # This operation should have access to all models. Ensure that all models are
 
     # This operation should have access to all models. Ensure that all models are
 
     # reloaded in case any are delayed.
 
     # reloaded in case any are delayed.
 
     from_state.clear_delayed_apps_cache()
 
     from_state.clear_delayed_apps_cache()
     ...</pre>
+
     ...</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div></li>
 
</div></li>
<li><p><code>to_state</code> in the database_backwards method is the ''older'' state; that is,
+
<li><p>database_backwards方法中的<code>to_state</code>''older''状态; 也就是说,一旦迁移完成逆转,它将成为当前状态。</p></li>
the one that will be the current state once the migration has finished reversing.</p></li>
+
<li><p>您可能会在内置操作中看到 <code>references_model</code> 的实现; 这是自动检测代码的一部分,与自定义操作无关。</p></li></ul>
<li><p>You might see implementations of <code>references_model</code> on the built-in
 
operations; this is part of the autodetection code and does not matter for
 
custom operations.</p></li></ul>
 
  
 
<div class="admonition warning">
 
<div class="admonition warning">
第638行: 第497行:
 
警告
 
警告
  
For performance reasons, the [[../models/fields#django.db.models|<code>Field</code>]] instances in
+
出于性能原因,<code>ModelState.fields</code> 中的 [[../models/fields#django.db.models|Field]] 实例在迁移中重复使用。 您绝不能更改这些实例的属性。 如果需要修改 <code>state_forwards()</code> 中的字段,则必须从 <code>ModelState.fields</code> 中删除旧实例并在其位置添加新实例。 <code>ModelState.managers</code> 中的 [[../../topics/db/managers#django.db.models|Manager]] 实例也是如此。
<code>ModelState.fields</code> are reused across migrations. You must never change
 
the attributes on these instances. If you need to mutate a field in
 
<code>state_forwards()</code>, you must remove the old instance from
 
<code>ModelState.fields</code> and add a new instance in its place. The same is true
 
for the [[../../topics/db/managers#django.db.models|<code>Manager</code>]] instances in
 
<code>ModelState.managers</code>.
 
  
  
 
</div>
 
</div>
As a simple example, let's make an operation that loads PostgreSQL extensions
+
作为一个简单的例子,让我们做一个加载 PostgreSQL 扩展(包含一些 PostgreSQL 更令人兴奋的特性)的操作。 这很简单; 没有模型状态更改,它所做的只是运行一个命令:
(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:
 
  
 
<div class="highlight-default notranslate">
 
<div class="highlight-default notranslate">
第656行: 第507行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>from django.db.migrations.operations.base import Operation
+
<syntaxhighlight lang="python">from django.db.migrations.operations.base import Operation
  
 
class LoadExtension(Operation):
 
class LoadExtension(Operation):
第669行: 第520行:
  
 
     def database_forwards(self, app_label, schema_editor, from_state, to_state):
 
     def database_forwards(self, app_label, schema_editor, from_state, to_state):
         schema_editor.execute(&quot;CREATE EXTENSION IF NOT EXISTS %s&quot; % self.name)
+
         schema_editor.execute("CREATE EXTENSION IF NOT EXISTS %s" % self.name)
  
 
     def database_backwards(self, app_label, schema_editor, from_state, to_state):
 
     def database_backwards(self, app_label, schema_editor, from_state, to_state):
         schema_editor.execute(&quot;DROP EXTENSION %s&quot; % self.name)
+
         schema_editor.execute("DROP EXTENSION %s" % self.name)
  
 
     def describe(self):
 
     def describe(self):
         return &quot;Creates extension %s&quot; % self.name</pre>
+
         return "Creates extension %s" % self.name</syntaxhighlight>
  
 
</div>
 
</div>
第684行: 第535行:
  
 
</div>
 
</div>
 +
<div class="clearer">
  
[[Category:Django 2.2.x 中文文档]]
+
 
 +
 
 +
</div>
 +
 
 +
[[Category:Django 2.2.x 文档]]

2021年10月31日 (日) 04:05的最新版本

迁移操作

迁移文件由一个或多个 Operation 组成,这些对象声明性地记录迁移应该对您的数据库执行的操作。

Django 还使用这些 Operation 对象来计算您的模型在历史上的样子,并计算自上次迁移以来您对模型所做的更改,以便它可以自动编写您的迁移; 这就是为什么它们是声明性的,因为这意味着 Django 可以轻松地将它们全部加载到内存中并在不接触数据库的情况下运行它们来计算出您的项目应该是什么样子。

还有更专门的 Operation 对象,用于 数据迁移 和高级手动数据库操作。 如果您想封装通常所做的自定义更改,您还可以编写自己的 Operation 类。

如果您需要一个空的迁移文件来写入您自己的 Operation 对象,只需使用 python manage.py makemigrations --empty yourappname,但请注意,手动添加模式更改操作可能会混淆迁移自动检测器并使结果运行 [ X225X]:djadmin:`makemigrations` 输出错误的代码。

所有核心 Django 操作都可以从 django.db.migrations.operations 模块获得。

有关介绍性材料,请参阅 迁移主题指南

架构操作

CreateModel

class CreateModel(name, fields, options=None, bases=None, managers=None)

在项目历史中创建一个新的模型,并在数据库中创建与之匹配的相应表。

name 是型号名称,如 models.py 文件中所写。

fields(field_name, field_instance) 的二元组列表。 字段实例应该是一个未绑定的字段(所以只是 models.CharField(...),而不是取自另一个模型的字段)。

options 是来自模型的 Meta 类的可选值字典。

bases 是一个可选的其他类的列表,让这个模型继承; 如果您想依赖另一个模型(因此您从历史版本继承),它可以包含格式为 "appname.ModelName" 的类对象和字符串。 如果未提供,则默认为仅从标准 models.Model 继承。

managers 获取 (manager_name, manager_instance) 的 2 元组列表。 列表中的第一个管理器将是迁移期间此模型的默认管理器。


DeleteModel

class DeleteModel(name)

从项目历史中删除模型,并从数据库中删除它的表。


RenameModel

class RenameModel(old_name, new_name)

将模型从旧名称改名为新名称。

如果您一次更改模型的名称及其相当多的字段,则可能需要手动添加它; 对于自动检测器,这看起来就像您删除了具有旧名称的模型并添加了具有不同名称的新模型,并且它创建的迁移将丢失旧表中的所有数据。


AlterModelTable

class AlterModelTable(name, table)

更改模型的表名(Meta 子类上的 db_table 选项)。


AlterUniqueTogether

class AlterUniqueTogether(name, unique_together)

更改模型的唯一约束集(Meta 子类上的 unique_together 选项)。


AlterIndexTogether

class AlterIndexTogether(name, index_together)

更改模型的自定义索引集(Meta 子类上的 index_together 选项)。


AlterOrderWithRespectTo

class AlterOrderWithRespectTo(name, order_with_respect_to)

创建或删除 Meta 子类上的 order_with_respect_to 选项所需的 _order 列。


AlterModelOptions

class AlterModelOptions(name, options)

存储对其他模型选项(模型 Meta 上的设置)的更改,例如 permissionsverbose_name。 不会影响数据库,但会保留这些更改以供 RunPython 实例使用。 options 应该是将选项名称映射到值的字典。


AlterModelManagers

class AlterModelManagers(name, managers)

改变迁移期间可用的管理器。


AddField

class AddField(model_name, name, field, preserve_default=True)

向模型添加字段。 model_name 是模型的名称,name 是字段的名称,field 是一个未绑定的 Field 实例(你会在 [X162X ] - 例如,models.IntegerField(null=True)

preserve_default 参数表示该字段的默认值是否是永久的并且应该被烘焙到项目状态 (True),或者它是否是临时的并且仅用于此迁移 (False ) - 通常是因为迁移正在向表中添加不可为空的字段,并且需要将默认值放入现有行中。 它不会直接影响在数据库中设置默认值的行为 - Django 从不设置数据库默认值,而是始终将它们应用到 Django ORM 代码中。

警告

在较旧的数据库上,添加具有默认值的字段可能会导致表的完全重写。 即使对于可为空的字段也会发生这种情况,并且可能会对性能产生负面影响。 为避免这种情况,应采取以下步骤。

  • 添加没有默认值的可空字段并运行 :djadmin:`makemigrations` 命令。 这应该会生成一个带有 AddField 操作的迁移。
  • 将默认值添加到您的字段并运行 :djadmin:`makemigrations` 命令。 这应该会生成一个带有 AlterField 操作的迁移。


RemoveField

class RemoveField(model_name, name)

从模型中删除一个字段。

请记住,当相反时,这实际上是向模型添加一个字段。 如果该字段可以为空或者它具有可用于填充重新创建的列的默认值,则该操作是可逆的(除了任何数据丢失,这当然是不可逆的)。 如果该字段不可为空且没有默认值,则该操作是不可逆的。


AlterField

class AlterField(model_name, name, field, preserve_default=True)

更改字段的定义,包括更改其类型、nulluniquedb_column 和其他字段属性。

preserve_default 参数表示该字段的默认值是否是永久的并且应该被烘焙到项目状态 (True),或者它是否是临时的并且仅用于此迁移 (False ) - 通常是因为迁移将可空字段更改为不可空字段,并且需要将默认值放入现有行。 它不会直接影响在数据库中设置默认值的行为 - Django 从不设置数据库默认值,而是始终将它们应用到 Django ORM 代码中。

请注意,并非所有数据库都可以进行所有更改 - 例如,在大多数数据库上,您不能将 models.TextField() 之类的文本类型字段更改为 models.IntegerField() 之类的数字类型字段。


RenameField

class RenameField(model_name, old_name, new_name)

更改字段的名称(并且,除非设置了 db_column,则更改其列名称)。


AddIndex

class AddIndex(model_name, index)

在数据库表中为具有 model_name 的模型创建索引。 indexIndex 类的一个实例。


RemoveIndex

class RemoveIndex(model_name, name)

从带有 model_name 的模型中删除名为 name 的索引。


AddConstraint

class AddConstraint(model_name, constraint)

2.2 版中的新功能。


在数据库表中为具有 model_name 的模型创建 约束


RemoveConstraint

class RemoveConstraint(model_name, name)

2.2 版中的新功能。


从具有 model_name 的模型中移除名为 name 的约束。


特殊操作

RunSQL

class RunSQL(sql, reverse_sql=None, state_operations=None, hints=None, elidable=False)

允许在数据库上运行任意 SQL - 对于 Django 不直接支持的数据库后端的更高级功能非常有用,例如部分索引。

sqlreverse_sql(如果提供)应该是在数据库上运行的 SQL 字符串。 在大多数数据库后端(除了 PostgreSQL 之外),Django 会在执行之前将 SQL 拆分为单独的语句。

您还可以传递字符串列表或 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'])])

如果你想在查询中包含字面的百分号,如果你传递的是参数,你必须将它们翻倍。

reverse_sql 查询在未应用迁移时执行,因此您可以撤消在转发查询中所做的更改:

migrations.RunSQL(
    [("INSERT INTO musician (name) VALUES (%s);", ['Reinhardt'])],
    [("DELETE FROM musician where name=%s;", ['Reinhardt'])],
)

state_operations 参数使您可以提供在项目状态方面与 SQL 等效的操作; 例如,如果您手动创建列,则应在此处传入包含 AddField 操作的列表,以便自动检测器仍具有模型的最新状态(否则,当您下次运行时makemigrations,它不会看到任何添加该字段的操作,因此将尝试再次运行它)。 例如:

migrations.RunSQL(
    "ALTER TABLE musician ADD COLUMN name varchar(255) NOT NULL;",
    state_operations=[
        migrations.AddField(
            'musician',
            'name',
            models.CharField(max_length=255),
        ),
    ],
)

可选的 hints 参数将作为 **hints 传递给数据库路由器的 allow_migrate() 方法,以帮助它们做出路由决策。 有关数据库提示的更多详细信息,请参阅 Hints

可选的 elidable 参数确定在 挤压迁移 时是否删除(省略)该操作。

RunSQL.noop
当您希望操作不在给定方向上执行任何操作时,将 RunSQL.noop 属性传递给 sqlreverse_sql。 这在使操作可逆时特别有用。


RunPython

class RunPython(code, reverse_code=None, atomic=None, hints=None, elidable=False)

在历史上下文中运行自定义 Python 代码。 code(和 reverse_code 如果提供)应该是接受两个参数的可调用对象; 第一个是 django.apps.registry.Apps 的实例,其中包含与操作在项目历史中的位置相匹配的历史模型,第二个是 SchemaEditor 的实例。

reverse_code 参数在取消应用迁移时被调用。 这个 callable 应该撤消在 code callable 中所做的事情,以便迁移是可逆的。

可选的 hints 参数将作为 **hints 传递给数据库路由器的 allow_migrate() 方法,以帮助它们做出路由决策。 有关数据库提示的更多详细信息,请参阅 Hints

可选的 elidable 参数确定在 挤压迁移 时是否删除(省略)该操作。

建议将代码写成迁移文件中Migration类上面的单独函数,直接传给RunPython即可。 下面是使用 RunPythonCountry 模型上创建一些初始对象的示例:

from django.db import 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"),
    ])

def reverse_func(apps, schema_editor):
    # forwards_func() creates two Country instances,
    # so reverse_func() should delete them.
    Country = apps.get_model("myapp", "Country")
    db_alias = schema_editor.connection.alias
    Country.objects.using(db_alias).filter(name="USA", code="us").delete()
    Country.objects.using(db_alias).filter(name="France", code="fr").delete()

class Migration(migrations.Migration):

    dependencies = []

    operations = [
        migrations.RunPython(forwards_func, reverse_func),
    ]

这通常是您用于创建 数据迁移 、运行自定义数据更新和更改以及您需要访问 ORM 和/或 Python 代码的任何其他操作的操作。

如果您是从 South 升级,这基本上是作为操作的 South 模式 - 一种或两种向前和向后的方法,以及可用的 ORM 和模式操作。 大多数情况下,您应该能够将来自 South 的 orm.Modelorm["appname", "Model"] 引用直接转换为 apps.get_model("appname", "Model") 引用,并保留大部分其余代码的数据不变迁移。 但是,apps 将只引用当前应用程序中的模型,除非其他应用程序中的迁移被添加到迁移的依赖项中。

很像 RunSQL,确保如果你在这里改变架构,你要么在 Django 模型系统的范围之外做它(例如 触发器) 或者您使用 SeparateDatabaseAndState 添加将反映您对模型状态更改的操作 - 否则,版本化 ORM 和自动检测器将停止正常工作。

默认情况下,RunPython 将在不支持 DDL 事务的数据库(例如 MySQL 和 Oracle)上的事务中运行其内容。 这应该是安全的,但如果您尝试使用这些后端提供的 schema_editor,可能会导致崩溃; 在这种情况下,将 atomic=False 传递给 RunPython 操作。

在支持 DDL 事务(SQLite 和 PostgreSQL)的数据库上,除了为每次迁移创建的事务之外,RunPython 操作不会自动添加任何事务。 因此,例如,在 PostgreSQL 上,您应该避免在同一迁移中组合架构更改和 RunPython 操作,否则您可能会遇到类似 OperationalError: cannot ALTER TABLE "mytable" because it has pending trigger events 的错误。

如果您有不同的数据库并且不确定它是否支持 DDL 事务,请检查 django.db.connection.features.can_rollback_ddl 属性。

如果 RunPython 操作是 非原子迁移 的一部分,则只有将 atomic=True 传递给 RunPython,该操作才会在事务中执行手术。

警告

RunPython 不会为你神奇地改变模型的连接; 您调用的任何模型方法都将转到默认数据库,除非您为它们提供当前数据库别名(可从 schema_editor.connection.alias 获得,其中 schema_editor 是您函数的第二个参数)。


static RunPython.noop()
当您希望操作在给定方向上不执行任何操作时,将 RunPython.noop 方法传递给 codereverse_code。 这在使操作可逆时特别有用。


SeparateDatabaseAndState

class SeparateDatabaseAndState(database_operations=None, state_operations=None)

一个高度专业化的操作,让你混合和匹配数据库(架构改变)和状态(自动检测器支持)方面的操作。

它接受两个操作列表,当被要求应用状态时将使用状态列表,当被要求对数据库应用更改时将使用数据库列表。 除非您非常确定自己知道自己在做什么,否则不要使用此操作。


自己写

操作有一个相对简单的 API,它们的设计使您可以轻松地编写自己的 API 来补充内置的 Django API。 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 和用于获取历史模型的模式,以及 ModelState 和用于改变 state_forwards() 中的历史模型的模式。

注意事项:

  • 你不需要学习太多 ProjectState 来编写简单的迁移; 只知道它有一个 apps 属性,可以访问应用程序注册表(然后您可以调用 get_model)。

  • database_forwardsdatabase_backwards 都得到两个传递给它们的状态; 这些仅代表 state_forwards 方法将应用的差异,但出于方便和速度的原因提供给您。

  • 如果要使用 database_forwards()database_backwards() 中的 from_state 参数中的模型类或模型实例,则必须使用 clear_delayed_apps_cache() 方法渲染模型状态以提供相关模型:

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        # This operation should have access to all models. Ensure that all models are
        # reloaded in case any are delayed.
        from_state.clear_delayed_apps_cache()
        ...
  • database_backwards方法中的to_stateolder状态; 也就是说,一旦迁移完成逆转,它将成为当前状态。

  • 您可能会在内置操作中看到 references_model 的实现; 这是自动检测代码的一部分,与自定义操作无关。

警告

出于性能原因,ModelState.fields 中的 Field 实例在迁移中重复使用。 您绝不能更改这些实例的属性。 如果需要修改 state_forwards() 中的字段,则必须从 ModelState.fields 中删除旧实例并在其位置添加新实例。 ModelState.managers 中的 Manager 实例也是如此。


作为一个简单的例子,让我们做一个加载 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