模型 Meta 选项

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

可用的 Meta 选项

abstract

Options.abstract

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

app_label

Options.app_label

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

app_label = 'myapp'

如果你想用 app_label.object_nameapp_label.model_name 来表示一个模型,你可以分别使用 model._meta.labelmodel._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 管理器名称。

get_latest_by

Options.get_latest_by

模型中的字段名或字段名列表,通常是 DateFieldDateTimeFieldIntegerField。这指定了在你的模型中使用的默认字段 Managerlast()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_toordering 不能同时使用,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

使用 UniqueConstraintconstraint 选项代替。

UniqueConstraintunique_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'