SchemaEditor
Django 的迁移系统分为两部分,一部分是计算和存储应该运行哪些操作的逻辑(django.db.migrations
),另一部分是将“创建模型”或“删除字段”这样的事情变成 SQL 的数据库抽象层——这是 SchemaEditor
的工作。
作为一个使用 Django 的普通开发者,你不太可能想直接与 SchemaEditor
进行交互,但如果你想写自己的迁移系统,或者有更高级的需求,它比写 SQL 要好得多。
Django 中的每个数据库后端都提供了自己的 SchemaEditor
版本,并且总是通过 connection.schema_editor()
上下文管理器:
with connection.schema_editor() as schema_editor:
schema_editor.delete_model(MyModel)
它必须通过上下文管理器使用,因为这允许它管理诸如事务和延迟 SQL(如创建 ForeignKey
约束)的事情。
它将所有可能的操作以方法的形式展现出来,这些方法应该按照你希望的改变顺序被调用。有些可能的操作或更改类型并不是在所有的数据库中都能实现——例如,MyISAM 不支持外键约束。
如果你正在为 Django 编写或维护一个第三方数据库后端,你将需要提供一个 SchemaEditor
的实现,以便与 Django 的迁移功能一起工作——不过,只要你的数据库在使用 SQL 和关系型设计方面比较标准,你应该能够将 Django 内置的 SchemaEditor
类子类化,并对语法进行一些调整。
方法
alter_unique_together()
改变模型的 unique_together
值;这将从模型的表中添加或删除唯一约束,直到它们与新的值相匹配。
alter_index_together()
更改模型的 index_together
值;这将从模型的表中添加或删除索引,直到它们与新值相匹配。
add_field()
在模型的表中添加一列(或有时是多列)来表示该字段。如果字段有 db_index=True
或 unique=True
,还将添加索引或唯一约束。
如果字段是 ManyToManyField
,没有 through
的值,它将不创建一列,而是制作一个表来表示这种关系。如果提供了 through
,则为无操作。
如果字段是 ForeignKey
,这也会将外键约束添加到列中。
remove_field()
从模型的表中删除代表字段的列,以及由该字段引起的任何唯一约束、外键约束或索引。
如果字段是一个 ManyToManyField,没有 through
的值,它将删除为跟踪关系而创建的表。如果提供了 through
,则为无操作。
alter_field()
这将模型上的字段从旧字段转换为新字段。这包括改变列的名称(db_column
属性),改变字段的类型(如果字段类发生变化),改变字段的 NULL
状态,添加或删除只属于字段的唯一约束和索引,改变主键,以及改变 ForeignKey
约束的目的地。
最常见的不能做的转换是将一个 ManyToManyField
转换为一个普通的 Field,反之亦然;Django 不能在不丢失数据的情况下这样做,所以它会拒绝这样做。相反, remove_field()
和 add_field()
应该分别调用。
如果数据库有 supports_combined_alters
,Django 会尝试在一次数据库调用中尽可能多地进行这些操作;否则,它会为每一个变化发出单独的 ALTER 语句,但不会在不需要变化的地方发出 ALTER。
属性
除非另有说明,否则所有属性都应被视为只读。
讨论区