模型Meta选项
慢慢补充
本文档介绍了可以在class Meta
内部为模型提供的所有可能的元数据选项。
1. 可用 Meta选项
abstract
如果abstract = True
,这个模型将是一个抽象基类。
app_label
如果在INSTALLED_APPS的应用程序之外定义模型 ,则必须声明它属于哪个应用程序:
app_label = 'myapp'
如果要表示具有app_label.object_name 格式或app_label.model_name格式的模型,或者您可以分别使用model._meta.label 或model._meta.label_lower。
译者实例:
ABook
模型类本属于sample_mode
这个app,但我却把它写在了starks
这个app里面了,为了声明它属于sample_mode
,增加了app_label属性。
引用模型的时候,只能从starks里面找,所以容易混淆,你就不要把它们分开。
base_manager_name
用于模型的管理器的名称 _base_manager。
译者实例:
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
def __str__(self):
return self.name
class Meta:
base_manager_name = 'oo'
b = Publish.objects.get(pk=1)
print(b._meta.base_manager_name)
#输出结果
oo
db_table
用于模型在数据库中表的名称:
db_table = 'self_table_name'
表名
为了节省您的时间,Django会自动从模型类的名称和包含它的应用程序中派生数据库表的名称。模型的数据库表名称是通过将模型的“应用程序标签”(您在manage.py startapp
中使用的名称)加入模型的类名称,并在它们之间加下划线来构建的。
例如,如果您有一个应用程序bookstore(由创建者使用manage.py startapp bookstore
创建 ),则定义为class Book
的模型将具有名为bookstore_book
的数据库表。
要覆盖数据库表名,请在class Meta
内使用db_table
参数覆盖 。
如果您的数据库表名是SQL保留字,或者包含Python变量名中不允许的字符 - 特别是连字符 - 没问题。Django在幕后用引号引起了了列名和表名(译者注:别给自己找麻烦)。
为MySQL使用小写表名
强烈建议您在覆盖表名时使用小写表名,特别是在使用MySQL后端时。有关更多详细信息,请参阅 MySQL注意事项。↑
Oracle的表名称引用
为了满足Oracle对表名的限制(30个字符),并且符合Oracle数据库的常规约定,Django可能会缩短表名并将它们全部大写。要阻止此类转换,请使用带引号的名称作为db_table的值:
db_table = '"name_left_in_lowercase"'
这些引用的名称也可以与Django其他支持的数据库后端一起使用; 但是,除了Oracle之外,引号都没有效果。有关更多详细信息,请参阅 Oracle 注意事项。↑
db_tablespace
用于此模型的数据库表空间的名称。默认为项目的DEFAULT_TABLESPACE 设置(如果已设置)。如果后端不支持表空间,则忽略此选项。
default_manager_name
用于模型的管理器的名称。
default_related_name
默认情况下将用于从相关对象返回到此对象的关系的名称。默认是<model_name>_set
。
此选项也设置related_query_name。
由于字段的反向名称应该是唯一的,因此如果您打算对模型进行子类化,请务必小心。要解决名称冲突,名称的一部分应该包含'%(app_label)s'
和'%(model_name)s'
,它们分别由模型所在的应用程序的名称和模型的名称替换,两者都是小写的。请参阅 抽象模型关联名称 。
get_latest_by
模型字段中的一个字段的名称或字段名称的列表,通常是DateField,DateTimeField或IntegerField。这指定在模型中Manager使用的 latest()和 earliest()方法的一个或多个字段。
例:
# Latest by ascending order_date.
get_latest_by = "order_date"
# Latest by priority descending, order_date ascending.
get_latest_by = ['-priority', 'order_date']
有关latest()更多信息,请参阅文档。
在Django 2.0中更改:
添加了对字段列表的支持。
managed
默认为True,意味着Django将在migrate迁移中或作为迁移的一部分创建适当的数据库表,并将其作为flush管理命令的一部分删除。也就是说,Django 管理数据库表的生命周期。
如果设置为False,不会对此模型执行数据库表创建或删除操作。如果模型表示通过其他方式创建的现有表或数据库视图,则此选项非常有用。这是两种选项的唯一区别。模型处理的所有其他方面与正常情况完全相同。这包括
-
如果未声明,则将自动主键字段添加到模型。为避免以后的代码阅读器混淆,建议在使用非托管模型时指定您正在建模的数据库表中的所有列。
-
如果managed=False,且模型包含一个 ManyToManyField字段指向另一个非托管模型,则也不会创建多对多联接的中间表。但是,将创建一个托管模型和一个非托管模型之间的中间表。
如果需要更改此默认行为,请将中间表创建为显式模型(managed根据需要设置),并使用ManyToManyField.through属性使关系使用自定义模型。
对于包含managed=False
的模型的测试,由您来确保在测试设置中创建正确的表。
如果您对更改Python级模型类的行为感兴趣,可以使用managed=False
并创建现有模型的副本。但是,对于这种情况,有一种更好的方法:代理模型。
order_with_respect_to
使该对象相对于给定字段可排序,通常用在ForeignKey上。例如,如果一个Answer对象与一个Question对象相关连,并且一个Question有一个以上的Answer,并且Answer的顺序很重要,那么你可以这样做:
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对象的顺序:
>>> 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添加了新的数据库列,所以如果order_with_respect_to在初始化后添加或更改,请务必进行相应的迁移 migrate。↑