# Django 3.2.11.dev 文档

# 模型 `Meta` 选项

本文档解释了所有可能的 元数据选项，你可以在模型的内部 `class Meta` 中为模型提供这些选项。

## 可用的 `Meta` 选项

### `abstract`

`Options.``abstract`

  如果 `abstract = True`，这个模型将是一个 抽象基类。

### `app_label`

`Options.``app_label`

  如果在 `INSTALLED_APPS` 中定义了一个应用程序之外的模型，它必须声明它属于哪个应用程序：

      app_label = 'myapp'

  如果你想用 `app_label.object_name` 或 `app_label.model_name` 来表示一个模型，你可以分别使用 `model._meta.label` 或 `model._meta.label_lower`。

### `base_manager_name`

`Options.``base_manager_name`

  管理器的属性名，例如，`'objects'`，用于模型的 `_base_manager`。

### `db_table`

`Options.``db_table`

  用于模型的数据库表的名称：

      db_table = 'music_album'

#### 表名称

为了节省你的时间，Django 会自动从你的模型类和包含它的应用程序的名称中导出数据库表的名称。一个模型的数据库表名是通过将模型的“app label”——你在 `manage.py startapp` 中使用的名称——与模型的类名连接起来，并在两者之间加上下划线。

例如，如果你有一个应用程序 `bookstore` （由 `manage.py startapp bookstore` 创建），一个定义为 `class Book` 的模型将有一个名为 `bookstore_book` 的数据库表。

要覆盖数据库表名，使用 `class Meta` 中的 `db_table` 参数。

如果你的数据库表名是 SQL 的保留字，或者包含 Python 变量名中不允许的字符——特别是连字符——那也没关系。Django 会在幕后引用列名和表名。

在 MariaDB 和 MySQL 中使用小写的表名

当你通过 `db_table` 覆盖表名时，强烈建议你使用小写的表名，特别是当你使用 MySQL 后端时。更多细节请参见 MySQL 注解。

Oracle 的表名引用

为了满足 Oracle 对表名的 30 个字符的限制，并符合 Oracle 数据库的惯例，Django 可能会缩短表名，并将其全部变成大写。为了防止这样的转变，使用带引号的名称作为 `db_table` 的值：

    db_table = '"name_left_in_lowercase"'

这样的引号也可以用在 Django 的其他支持的数据库后端，但是除了 Oracle，引号没有任何作用。更多细节请参见 Oracle 注解。

### `db_tablespace`

`Options.``db_tablespace`

  此模型要使用的 数据库表空间 名称。如果有设置的话，默认是项目的 `DEFAULT_TABLESPACE` 配置。如果后端不支持表空间，则忽略此选项。

### `default_manager_name`

`Options.``default_manager_name`

  模型的 `_default_manager` 管理器名称。

### `default_related_name`

`Options.``default_related_name`

  从相关对象到这个对象的关系默认使用的名称。默认为 `_set`。

  这个选项还可以设置 `related_query_name`。

  由于字段的反向名称应该是唯一的，所以如果你打算对你的模型进行子类化，就要小心了。为了避免名称冲突，名称的一部分应该包含 `'%(app_label)s'` 和 `'%(model_name)s'`，它们分别被模型所在的应用程序的名称和模型的名称所取代，都是小写的。见 抽象模型的相关名称 段落。

### `get_latest_by`

`Options.``get_latest_by`

  模型中的字段名或字段名列表，通常是 `DateField`，`DateTimeField` 或 `IntegerField`。这指定了在你的模型中使用的默认字段 `Manager` 的 `last()` 和 `earliest()` 方法。

  举例：

      # Latest by ascending order_date.
      get_latest_by = "order_date"

      # Latest by priority descending, order_date ascending.
      get_latest_by = ['-priority', 'order_date']

  更多内容请参见 `last()` 文档。

### `managed`

`Options.``managed`

  默认为 `True`，意味着 Django 会在 `migrate` 中创建相应的数据库表，或者作为迁移的一部分，并作为 `flush` 管理命令的一部分删除它们。也就是说，Django 管理 数据库表的生命周期。

  如果 `False`，将不对该模型进行数据库表的创建、修改或删除操作。如果该模型代表一个现有的表或一个通过其他方式创建的数据库视图，这一点很有用。这是在 `managed=False` 时 唯一 的区别。模型处理的所有其他方面都与正常情况完全相同。这包括

  1. 如果不声明的话，在模型中增加一个自动主键字段。 为了避免给后面来的代码读者带来困惑，建议在使用非托管模型时，指定你所建模的数据库表的所有列。

  2. 如果一个带有 `managed=False` 的模型包含一个 `ManyToManyField` 指向另一个非托管模型，那么多对多连接的中间表也不会被创建。但是，一个托管模型和一个非托管模型之间的中间表会被创建。

     如果你需要改变这种默认行为，请将中间表创建为显式模型（根据需要设置 `managed` ），并使用 `ManyToManyField.through` 属性让关系使用你的自定义模型。

  对于涉及 `managed=False` 模型的测试，你要确保创建正确的表作为测试设置的一部分。

  如果你对改变模型类的 Python 级行为感兴趣，你可以使用 `managed=False` 并创建一个现有模型的副本。然而，对于这种情况，有一个更好的方法： 代理模型。

### `order_with_respect_to`

`Options.``order_with_respect_to`

  使该对象可以根据给定字段（通常是 `ForeignKey` ）进行排序。这可以用来使相关对象相对于父对象可排序。例如，如果一个 `Answer` 与一个 `Question` 对象相关，而一个问题有多个答案，并且答案的顺序很重要，你可以这样做：

      from django.db import models

      class Question(models.Model):
          text = models.TextField()
          # ...

      class Answer(models.Model):
          question = models.ForeignKey(Question, on_delete=models.CASCADE)
          # ...

          class Meta:
              order_with_respect_to = 'question'

  当设置了 `order_with_respect_to` 时，还提供了两个额外的方法来检索和设置相关对象的顺序：`get_RELATED_order()` 和 `set_RELATED_order()`。`get_RELATED_order()` 和 `set_RELATED_order()`，其中 `RELATED` 是小写的模型名称。例如，假设一个 `Question` 对象有多个相关的 `Answer` 对象，返回的列表包含相关 `Answer` 对象的主键：

      >>> question = Question.objects.get(id=1)
      >>> question.get_answer_order()
      [1, 2, 3]

  Question` 对象的相关 `Answer` 对象的顺序可以通过传递 `Answer` 主键列表来设置：

      >>> question.set_answer_order([3, 1, 2])

  相关对象还得到两个方法，`get_next_in_order()` 和 `get_previous_in_order()`，这两个方法可以用来按照正确的顺序访问这些对象。假设 `Answer` 对象按 `id` 排序：

      >>> answer = Answer.objects.get(id=2)
      >>> answer.get_next_in_order()
      <Answer: 3>
      >>> answer.get_previous_in_order()
      <Answer: 1>

`order_with_respect_to` 隐式地设置 `ordering` 选项。

在内部，`order_with_respect_to` 增加了一个名为 `_order` 的额外字段／数据库列，并将模型的 `ordering` 选项设置为这个字段。因此，`order_with_respect_to` 和 `ordering` 不能同时使用，`order_with_respect_to` 所添加的排序将在每次获取这个模型的对象列表时应用。

更改 `order_with_respect_to`

因为 `order_with_respect_to` 增加了一个新的数据库列，所以如果你在初始 `migrate` 之后添加或更改 `order_with_respect_to`，请务必进行适当的迁移。

### `ordering`

`Options.``ordering`

  对象的默认排序，用于获取对象列表时：

      ordering = ['-order_date']

  这是一个字符串和／或查询表达式的元组或列表。每一个字符串都是一个字段名，前面有一个可选的“-”字头，表示降序。没有前缀“-”的字段将按升序排列。使用字符串“?”来随机排序。

  例如，要按 `pub_date` 字段升序排列，使用以下方法：

      ordering = ['pub_date']

  要按 `pub_date` 降序排列，请使用：

      ordering = ['-pub_date']

  要按 `pub_date` 降序，然后按 `author` 升序，请使用：

      ordering = ['-pub_date', 'author']

  你也可以使用 查询表达式。要按 `author` 升序排列，并使空值最后排序，请使用：

      from django.db.models import F

      ordering = [F('author').asc(nulls_last=True)]

警告

排序不是一个免费的操作。你添加到排序中的每个字段都会给你的数据库带来成本。你添加的每个外键都会隐式地包含其所有的默认排序。

如果查询没有指定顺序，那么结果将以未指定的顺序从数据库中返回。只有当按一组字段排序时，才能保证特定的排序，这些字段唯一地标识结果中的每个对象。例如，如果 `name` 字段不是唯一的，那么按它排序就不能保证具有相同名称的对象总是以相同的顺序出现。

### `permissions`

`Options.``permissions`

  创建此对象时要输入权限表的额外权限。为每个模型自动创建添加、更改、删除和查看权限。这个例子指定了一个额外的权限，`can_deliver_pizzas` ：

      permissions = [('can_deliver_pizzas', 'Can deliver pizzas')]

  这是一个由二元元组组成的列表或元组，格式为 `(permission_code, human_readable_permission_name)`。

### `default_permissions`

`Options.``default_permissions`

  默认值为 `('add', 'change', 'delete', 'view')` 。你可以自定义这个列表，例如，如果你的应用不需要任何默认的权限，可以将其设置为空列表。它必须在模型创建之前通过 `migrate` 在模型上指定，以防止任何遗漏的权限被创建。

### `proxy`

`Options.``proxy`

  如果 `proxy = True`，作为另一个模型子类的模型将被视为 代理模型。

### `required_db_features`

`Options.``required_db_features`

  当前连接应具备的数据库特征列表，以便在迁移阶段考虑模型。例如，如果你将此列表设置为 `['gis_enabled']`，则模型将只在支持 GIS 的数据库上同步。在使用多个数据库后端进行测试时，跳过一些模型也很有用。避免模型之间的关系，这些模型可能会被创建，也可能不会被创建，因为 ORM 不会处理这个问题。

### `required_db_vendor`

`Options.``required_db_vendor`

  本模型所特有的支持的数据库厂商名称。目前的内置厂商名称是： sqlite`，postgresql`，mysql` 和 oracle`。如果该属性不为空，且当前连接厂商与之不匹配，则该模型将不会同步。

### `select_on_save`

`Options.``select_on_save`

  确定 Django 是否会使用 1.6 之前的 `django.db.models.Model.save()` 算法。旧的算法使用 `SELECT` 来确定是否有一条现有的记录需要更新。新算法直接尝试 `UPDATE`。在一些罕见的情况下，Django 看不到现有行的 `UPDATE`。例如 PostgreSQL 的 `ON UPDATE` 触发器会返回 `NULL`。在这种情况下，即使数据库中存在一条记录，新算法最终也会进行 `INSERT`。

  通常不需要设置这个属性。默认值是 `False`。

  关于新旧保存算法，请参见 `django.db.models.Model.save()`。

### `indexes`

`Options.``indexes`

  你想在模型上定义的 indexes 的列表：

      from django.db import models

      class Customer(models.Model):
          first_name = models.CharField(max_length=100)
          last_name = models.CharField(max_length=100)

          class Meta:
              indexes = [
                  models.Index(fields=['last_name', 'first_name']),
                  models.Index(fields=['first_name'], name='first_name_idx'),
              ]

### `unique_together`

`Options.``unique_together`

  使用 `UniqueConstraint` 与 `constraint` 选项代替。

  `UniqueConstraint` 比 `unique_together` 提供更多的功能。`unique_together` 今后可能会被废弃。

  一组字段名，合起来必须是唯一的：

      unique_together = [['driver', 'restaurant']]

  这是一个列表，这些列表在一起考虑时必须是唯一的。它 在Django 管理中使用，并在数据库级别执行（即在 `CREATE TABLE` 语句中包含适当的 `UNIQUE` 语句）。

  为方便起见，`unique_together` 在处理单组字段时可以是一个单一的列表：

      unique_together = ['driver', 'restaurant']

  一个 `ManyToManyField` 不能被包含在 unique_together 中。（不清楚那意味着什么！）如果你需要验证与 `ManyToManyField` 相关的唯一性，可以尝试使用信号或显式 `through` 模型。

  在模型验证过程中，当约束条件被违反时引发的 `ValidationError` 具有 `unique_together` 错误代码。

### `index_together`

`Options.``index_together`

  使用 `indexes` 选项代替。

  新的 `indexes` 选项比 `index_together` 提供了更多的功能。`index_together` 今后可能会被废弃。

  一组字段名，合在一起，是有索引的：

      index_together = [
          ["pub_date", "deadline"],
      ]

  该字段清单将被编入索引（即发出适当的 `CREATE INDEX` 语句）。

  为方便起见，`index_together` 在处理一组字段时，可以是一个单一的列表：

      index_together = ["pub_date", "deadline"]

### `constraints`

`Options.``constraints`

  你想在模型上定义的 约束 列表：

      from django.db import models

      class Customer(models.Model):
          age = models.IntegerField()

          class Meta:
              constraints = [
                  models.CheckConstraint(check=models.Q(age__gte=18), name='age_gte_18'),
              ]

### `verbose_name`

`Options.``verbose_name`

  对象的可读名称，单数：

      verbose_name = "pizza"

  如果没有给定，Django 将使用一个 munged 版本的类名：`CamelCase` 变成 `camel case`。

### `verbose_name_plural`

`Options.``verbose_name_plural`

  对象的复数名称：

      verbose_name_plural = "stories"

  如果没有给定，Django 将使用 `verbose_name` + `"s"`。

## 只读的 `Meta` 属性

### `label`

`Options.``label`

  对象的表示，返回 `app_label.object_name`，例如 `'polls.Question'`。

### `label_lower`

`Options.``label_lower`

  模型的表示，返回 `app_label.model_name`，例如 `'polls.question'`。