---
title: "SchemaEditor"
version: 3.2
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/3.2/ref/schema-editor/
canonical: https://djangodocs.dev/zh-hans/3.2/ref/schema-editor/
---
# `SchemaEditor`

#### `class BaseDatabaseSchemaEditor`

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` 类子类化，并对语法进行一些调整。

## 方法

### `execute()`

#### `BaseDatabaseSchemaEditor.execute(sql, params=())`

执行传入的 SQL 语句，如果提供参数，则执行。这是一个围绕普通数据库游标的包装器，如果用户愿意，允许捕获 SQL 语句到 .sql\` 文件。

### `create_model()`

#### `BaseDatabaseSchemaEditor.create_model(model)`

在数据库中为所提供的模型创建一个新表，以及它所需要的任何唯一约束或索引。

### `delete_model()`

#### `BaseDatabaseSchemaEditor.delete_model(model)`

将模型的表连同它所拥有的任何唯一约束或索引一起在数据库中丢弃。

### `add_index()`

#### `BaseDatabaseSchemaEditor.add_index(model, index)`

在 `model` 的表中添加 `index`。

### `remove_index()`

#### `BaseDatabaseSchemaEditor.remove_index(model, index)`

将 `index` 从 `model` 的表中删除。

### `add_constraint()`

#### `BaseDatabaseSchemaEditor.add_constraint(model, constraint)`

在 `model` 的表中添加 `constraint`。

### `remove_constraint()`

#### `BaseDatabaseSchemaEditor.remove_constraint(model, constraint)`

将 `constraint` 从 `model` 的表中删除。

### `alter_unique_together()`

#### `BaseDatabaseSchemaEditor.alter_unique_together(model, old_unique_together, new_unique_together)`

改变模型的 [`unique_together`](/zh-hans/3.2/ref/models/options/#django.db.models.Options.unique_together) 值；这将从模型的表中添加或删除唯一约束，直到它们与新的值相匹配。

### `alter_index_together()`

#### `BaseDatabaseSchemaEditor.alter_index_together(model, old_index_together, new_index_together)`

更改模型的 [`index_together`](/zh-hans/3.2/ref/models/options/#django.db.models.Options.index_together) 值；这将从模型的表中添加或删除索引，直到它们与新值相匹配。

### `alter_db_table()`

#### `BaseDatabaseSchemaEditor.alter_db_table(model, old_db_table, new_db_table)`

将模型的表从 `old_db_table` 改名为 `new_db_table`。

### `alter_db_tablespace()`

#### `BaseDatabaseSchemaEditor.alter_db_tablespace(model, old_db_tablespace, new_db_tablespace)`

将模型的表从一个表空间移动到另一个表空间。

### `add_field()`

#### `BaseDatabaseSchemaEditor.add_field(model, field)`

在模型的表中添加一列（或有时是多列）来表示该字段。如果字段有 `db_index=True` 或 `unique=True`，还将添加索引或唯一约束。

如果字段是 `ManyToManyField`，没有 `through` 的值，它将不创建一列，而是制作一个表来表示这种关系。如果提供了 `through`，则为无操作。

如果字段是 `ForeignKey`，这也会将外键约束添加到列中。

### `remove_field()`

#### `BaseDatabaseSchemaEditor.remove_field(model, field)`

从模型的表中删除代表字段的列，以及由该字段引起的任何唯一约束、外键约束或索引。

如果字段是一个 ManyToManyField，没有 `through` 的值，它将删除为跟踪关系而创建的表。如果提供了 `through`，则为无操作。

### `alter_field()`

#### `BaseDatabaseSchemaEditor.alter_field(model, old_field, new_field, strict=False)`

这将模型上的字段从旧字段转换为新字段。这包括改变列的名称（[`db_column`](/zh-hans/3.2/ref/models/fields/#django.db.models.Field.db_column) 属性），改变字段的类型（如果字段类发生变化），改变字段的 `NULL` 状态，添加或删除只属于字段的唯一约束和索引，改变主键，以及改变 `ForeignKey` 约束的目的地。

最常见的不能做的转换是将一个 `ManyToManyField` 转换为一个普通的 Field，反之亦然；Django 不能在不丢失数据的情况下这样做，所以它会拒绝这样做。相反， [`remove_field()`](#django.db.backends.base.schema.BaseDatabaseSchemaEditor.remove_field) 和 [`add_field()`](#django.db.backends.base.schema.BaseDatabaseSchemaEditor.add_field) 应该分别调用。

如果数据库有 `supports_combined_alters`，Django 会尝试在一次数据库调用中尽可能多地进行这些操作；否则，它会为每一个变化发出单独的 ALTER 语句，但不会在不需要变化的地方发出 ALTER。

## 属性

除非另有说明，否则所有属性都应被视为只读。

### `connection`

#### `SchemaEditor.connection`

与数据库的连接对象。连接的一个有用属性是 `alias`，它可以用来确定被访问的数据库的名称。

这在为 [多数据库迁移](/zh-hans/3.2/howto/writing-migrations/#data-migrations-and-multiple-databases) 进行数据迁移时很有用。
