_meta
API¶model_meta
API是Django ORM的核心。 它使系统的其他部分(如查找,查询,表单和管理员)能够了解每个模型的功能。 API可通过每个模型类的_meta
属性访问,该属性是django.db.models.options.Options
对象的实例。
它提供的方法可以用于:
Options.
get_field
(field_name)[source]¶返回给定字段名称的字段实例。
field_name
可以是模型上的字段名称,抽象或继承模型上的字段,或在指向模型的另一个模型上定义的字段。 在后一种情况下,field_name
将是由用户定义的related_name
或由Django本身自动生成的名称。
如果找不到具有给定名称的字段,则会引发FieldDoesNotExist
异常。
>>> from django.contrib.auth.models import User
# A field on the model
>>> User._meta.get_field('username')
<django.db.models.fields.CharField: username>
# A field from another model that has a relation with the current model
>>> User._meta.get_field('logentry')
<ManyToOneRel: admin.logentry>
# A non existent field
>>> User._meta.get_field('does_not_exist')
Traceback (most recent call last):
...
FieldDoesNotExist: User has no field named 'does_not_exist'
Options.
get_fields
(include_parents=True, include_hidden=False)[source]¶返回与模型关联的字段的元组。 get_fields()
接受两个参数,可用于控制返回的字段:
include_parents
True
。 递归地包括在父类上定义的字段。 如果设置为False
,get_fields()
将只搜索在当前模型上直接声明的字段。 来自直接从抽象模型或代理类继承的模型的字段被认为是本地的,而不是父级的。include_hidden
False
。 如果设置为True
,则get_fields()
将包含用于返回其他字段功能的字段。 这还将包括具有以“+”开头的related_name
(例如ManyToManyField
或ForeignKey
)的任何字段。>>> from django.contrib.auth.models import User
>>> User._meta.get_fields()
(<ManyToOneRel: admin.logentry>,
<django.db.models.fields.AutoField: id>,
<django.db.models.fields.CharField: password>,
<django.db.models.fields.DateTimeField: last_login>,
<django.db.models.fields.BooleanField: is_superuser>,
<django.db.models.fields.CharField: username>,
<django.db.models.fields.CharField: first_name>,
<django.db.models.fields.CharField: last_name>,
<django.db.models.fields.EmailField: email>,
<django.db.models.fields.BooleanField: is_staff>,
<django.db.models.fields.BooleanField: is_active>,
<django.db.models.fields.DateTimeField: date_joined>,
<django.db.models.fields.related.ManyToManyField: groups>,
<django.db.models.fields.related.ManyToManyField: user_permissions>)
# Also include hidden fields.
>>> User._meta.get_fields(include_hidden=True)
(<ManyToOneRel: auth.user_groups>,
<ManyToOneRel: auth.user_user_permissions>,
<ManyToOneRel: admin.logentry>,
<django.db.models.fields.AutoField: id>,
<django.db.models.fields.CharField: password>,
<django.db.models.fields.DateTimeField: last_login>,
<django.db.models.fields.BooleanField: is_superuser>,
<django.db.models.fields.CharField: username>,
<django.db.models.fields.CharField: first_name>,
<django.db.models.fields.CharField: last_name>,
<django.db.models.fields.EmailField: email>,
<django.db.models.fields.BooleanField: is_staff>,
<django.db.models.fields.BooleanField: is_active>,
<django.db.models.fields.DateTimeField: date_joined>,
<django.db.models.fields.related.ManyToManyField: groups>,
<django.db.models.fields.related.ManyToManyField: user_permissions>)
作为Model._meta
API(从django.db.models.options.Options
类)的形式化的一部分,许多方法和属性已被弃用,将在Django 1.10中删除。
这些旧的API可以复制:
Options.get_field()
或;Options.get_fields()
以检索所有字段的列表,然后使用field attributes过滤此列表(或在_with_model
variant)所需字段的属性。虽然可以对旧方法进行严格等同的替换,但这可能不是最好的方法。 花费时间重构任何字段循环以更好地使用新的API - 并且可能包括先前被排除的字段 - 几乎肯定会导致更好的代码。
假设您有一个名为MyModel
的模型,可以进行以下替换,将代码转换为新的API:
MyModel._meta.get_field(name)
变成:
f = MyModel._meta.get_field(name)
然后检查:
f.auto_created == False
,因为新的get_field()
找到“反向”关系,并且:f.is_relation 和 f.related_model 无 t0 >,因为新的get_field()
API将找到GenericForeignKey
关系。
MyModel._meta.get_field_by_name(name)
使用以下替换返回这四个值的元组:
field
可以通过MyModel._meta.get_field(name)
model
可以通过字段上的model
属性找到。
direct
可以通过以下方式找到:不 field.auto_created 或 field.concrete
auto_created
检查排除由Django创建的所有“前进”和“反向”关系,但这也包括代理模型上的AutoField
和OneToOneField
。
我们避免使用concrete
属性过滤这些属性。
m2m
可以通过字段上的many_to_many
属性找到。
MyModel._meta.get_fields_with_model()
变成:
[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields()
if not f.is_relation
or f.one_to_one
or (f.many_to_one and f.related_model)
]
MyModel._meta.get_concrete_fields_with_model()
变成:
[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields()
if f.concrete and (
not f.is_relation
or f.one_to_one
or (f.many_to_one and f.related_model)
)
]
MyModel._meta.get_m2m_with_model()
变成:
[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields()
if f.many_to_many and not f.auto_created
]
MyModel._meta.get_all_related_objects()
变成:
[
f for f in MyModel._meta.get_fields()
if (f.one_to_many or f.one_to_one)
and f.auto_created and not f.concrete
]
MyModel._meta.get_all_related_objects_with_model()
变成:
[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields()
if (f.one_to_many or f.one_to_one)
and f.auto_created and not f.concrete
]
MyModel._meta.get_all_related_many_to_many_objects()
变成:
[
f for f in MyModel._meta.get_fields(include_hidden=True)
if f.many_to_many and f.auto_created
]
MyModel._meta.get_all_related_m2m_objects_with_model()
变成:
[
(f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields(include_hidden=True)
if f.many_to_many and f.auto_created
]
MyModel._meta.get_all_field_names()
变成:
from itertools import chain
list(set(chain.from_iterable(
(field.name, field.attname) if hasattr(field, 'attname') else (field.name,)
for field in MyModel._meta.get_fields()
# For complete backwards compatibility, you may want to exclude
# GenericForeignKey from the results.
if not (field.many_to_one and field.related_model is None)
)))
这提供了100%向后兼容的替换,确保包括字段名称和属性名称ForeignKey
,但与GenericForeignKey
相关联的字段不包括。 一个更简单的版本是:
[f.name for f in MyModel._meta.get_fields()]
虽然这不是100%向后兼容,但在许多情况下可能就足够了。
2017年9月6日