模型 Meta 选项

本篇文档阐述所有可用的 metadata 选项, 你可以在模型的 Meta 中设置它们.

Meta 可用选项

abstract

Options.abstract

如果设置 abstract = True, 改模型将成为 抽象基类.

app_label

Options.app_label

如果模型定义在 INSTALLED_APPS 之外, 那么必须声明其属于哪个app:

app_label = 'myapp'
New in Django 1.9:

如果想要使用 app_label.object_name 或者 app_label.model_name 来表示模型, 可以分别使用 model._meta.labelmodel._meta.label_lower.

base_manager_name

Options.base_manager_name
New in Django 1.10:

模型中 _base_manager 所使用的manager名称.

db_table

Options.db_table

该模型所使用的数据库表的名称:

db_table = 'music_album'

数据库表名

为节省时间, Django自动使用模型的名称和包含此模型的app名称来生成表名. 模型在数据库中的表名由模型的”app label” – 即在 manage.py startapp 中使用的名字和模型的类名通过下划线连接组成.

举个例子, 如果你有个名为 bookstore (通过 manage.py startapp bookstore 创建的) 的应用, 定义在 class Book 中的模型的数据库中的表名为 bookstore_book.

如果要重新数据库中的表名, 可以使用 class Meta 中的 db_table 参数.

如果你的数据库表名称是SQL保留字, 或包含Python变量名称中不允许的字符,特别是连字符 —- 这都不是问题. Django是在后台引用列和表名.

使用小写字符串作为 MySQL 表名

当你使用 db_table 重写数据库中表名时, 强烈建议你使用小写字符作为表名. 尤其是在使用MySQL作为后台数据库时. 详情参见 MySQL注意事项 .

Oracle中表名称的引号处理

为了遵从Oracle中30个字符的限制, 以及一些常见的约定, Django会缩短表的名称,而且会把它全部转为大写. 如果你不想名称按照预定设置发生变化, 可以在 db_table 的值外面加上引号来避免这种情况:

db_table = '"name_left_in_lowercase"'

这种带引号的名称也可以与Django所支持的其它数据库后端一起使用;但Oracle除外, 引号没有效果. 详情参见 Oracle 注意事项.

db_tablespace

Options.db_tablespace

当前模型所使用的 database tablespace 的名字. 默认值是项目设置中的 DEFAULT_TABLESPACE,如果后端并不支持表空间,这个选项可以忽略.

default_manager_name

Options.default_manager_name
New in Django 1.10:

模型中 _default_manager 用到的管理器名称.

get_latest_by

Options.get_latest_by

模型中可以用来排序的字段, 比如 DateField, DateTimeField, 或者 IntegerField. 它用来指定 模型中 Managerlatest()earliest() 方法的模型字段.

例如:

get_latest_by = "order_date"

详情请参考文档 latest() .

managed

Options.managed

默认为 True, 意味着Django将在 migrate 或作为迁移的一部分中创建适当的数据库表, 并将它们作为一个 flush management命令的一部分删除. 也就是说,Django 管理 数据库表的生命周期.

如果为 False, Django 就不会为当前模型创建和删除数据表. 这种适用于,当前模型使用一个已经存在的通过其它方法创建的数据表或数据库视图. 这是设置了 managed=False唯一 不同之处. 其它任何方面处理都和通常一样. 这包括:

  1. 如果没有声明,会自动向模型中添加一个自增主键. 为了避免给后面的代码读者带来混乱,当你在使用未被管理的模型时, 强烈推荐你指定(specify)数据表中所有的列.

  2. 如果模型设置了 managed=False 并且包含 ManyToManyField, 且这个多对多关联关系也指向一个没被管理(unmanaged)的模型, 那么这两个未被管理的模型的多对多关系的中间表也不会被创建. 但是, 一个被管理模型和一个未被管理模型之间的中间表就 被创建.

    如果需要修改这一默认行为,请将中间表创建为显式模型(根据需要设置 managed), 并使用 ManyToManyField.through . 通过属性使关系使用您的定制模型.

对于涉及 managed=False 模型的测试, 在测试之前, 必须要确保在测试启动时已经创建了正确的数据表。

如果你对在Python层面修改模型类行为感兴趣, 可以设置 managed=False, 并且为模型创建一个副本. 不过在这种场景下还有个更好的办法就是使用 代理模型.

order_with_respect_to

Options.order_with_respect_to

使此对象相对于给定字段可以排序, 通常为 ForeignKey. 这可以用于使关联的对象相对于父对象可排序. 比如, 如果 AnswerQuestion 关联, 一个问题有至少一个答案, 并且答案的顺序非常重要,你可以这样做:

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(), 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']

默认排序也会影响 聚合查询.

警告

排序并不是没有任何代价的操作. 你向ordering属性添加的每个字段都会产生数据库额外的开销. 添加的每个外键也会隐式包含它的默认顺序.

如果查询没有指定顺序, 则会以未指定的顺序从数据库返回结果. 仅当排序的一组字段可以唯一标识结果中的每个对象时, 才能保证稳定排序. 例如, 如果 name 字段不唯一, 则由其排序不会保证具有相同名称的对象总是以相同的顺序显示.

permissions

Options.permissions

创建对象时写入权限表中额外的权限. 每个模型将自动创建增加、删除和修改权限. 下面例子创建一个额外的权限 can_deliver_pizzas:

permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)

它是一个包含二元元组的列表或元组, 格式为 (权限编码, 书面的权限名称).

default_permissions

Options.default_permissions

默认为 ('add', 'change', 'delete'). 也可以自定义这个列表, 例如, 如果你的应用不需要默认权限中的任何一项, 可以把它设置成空列表. 这个属性必须在模型被 migrate 命令创建之前指定,避免一些遗漏的权限被创建.

proxy

Options.proxy

如果设置为 proxy = True,如果它是另一个模型的子类,将会视为一个 代理模型.

required_db_features

Options.required_db_features
New in Django 1.9:

当前连接的数据库应该具有的功能列表, 以便在迁移阶段考虑该模型. 例如,如果将此列表设置为 ['gis_enabled'], 则模型将仅在启用GIS的数据库上同步. 在使用多个数据库后端进行测试时, 用于跳过某些模型也很有用. 避免与ORM无关的模型之间的关系.

required_db_vendor

Options.required_db_vendor
New in Django 1.9:

该模型所特有的受支持的数据库种类的名称. 当前的内置数据库名称有: sqlite, postgresql, mysql, oracle. 如果该属性不是空, 且当前连接的数据库不匹配, 则模型将不会同步.

select_on_save

Options.select_on_save

该选项决定Django是否采用1.6之前的 django.db.models.Model.save() 算法. 旧的算法先使用 SELECT 来判断是否存在需要更新的行. 而新的算法直接尝试使用 UPDATE. 在某些少见的情况下, Django对已存在行的 UPDATE 操作不可访问. 比如, PostgreSQL的返回 NULLON UPDATE 触发器. 这种情况下,新式的算法最终会执行 INSERT 操作,即使这一行已经在数据库中存在.

通常这个属性不需要设置. 默认为 False.

关于旧式和新式两种保存算法, 请参见 django.db.models.Model.save().

unique_together

Options.unique_together

用来设置的不重复的字段组合:

unique_together = (("driver", "restaurant"),)

它是一个元组的元组, 组合起来的时候必须是唯一的. 它在Django admin层面使用, 在数据库层上进行数据约束(比如,在 CREATE TABLE 语句中使用 UNIQUE 语句).

为了方便起见, 处理单一字段的集合时, unique_together 可以是一维的元组:

unique_together = ("driver", "restaurant")

ManyToManyField 不能用在 unique_together中. (不清楚这样的含义是什么!), 如果需要验证 ManyToManyField 关联的唯一性, 可以尝试使用signal或者显式的 through 模型.

当违反 unique_together 约束时, 模型校验期间会抛出 ValidationError 异常.

index_together

Options.index_together

用来设置带有索引的字段组合:

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

将会为列表中的字段建立索引 (i.e. 会在 CREATE INDEX 语句中使用.)

为了方便起见, 处理单一字段的集合时, index_together 可以是一维的列表:

index_together = ["pub_date", "deadline"]

verbose_name

Options.verbose_name

对象的一个书面描述名字, 单数形式:

verbose_name = "pizza"

如果此项没有设置, Django会把类名拆分开来作为描述名, 比如 CamelCase 会变成 camel case.

verbose_name_plural

Options.verbose_name_plural

该对象复数形式的名称:

verbose_name_plural = "stories"

如果没有设置, Django 将使用 verbose_name + "s".

Meta 只读属性

label

Options.label
New in Django 1.9:

对象的表示, 返回 app_label.object_name, e.g. 'polls.Question'.

label_lower

Options.label_lower
New in Django 1.9:

模型的表示, 返回 app_label.model_name, e.g. 'polls.question'.