_meta是否是此规则的例外?它是否稳定且可用,还是将其视为不良实践?或者是否有函数或其他方式可以内省模型的字段而不使用_meta属性?以下是一些链接列表,显示如何使用_meta属性进行此操作。 任何建议都将不胜感激。 django object get/set field
_meta
是私有的,但它相对稳定。有人正在努力正式化、文档化并移除下划线,这可能会在1.3或1.4之前发生。我想会努力确保向后兼容性,因为许多人仍在使用它。
如果你特别关心兼容性,可以编写一个函数,接受模型并返回字段。这意味着如果将来有所改变,你只需要更改一个函数。
def get_model_fields(model):
return model._meta.fields
我相信这将返回一个Field
对象列表。要从实例中获取每个字段的值,请使用getattr(instance,field.name)
。
更新:Django贡献者正在开发API来替换_Meta_对象作为Google Summer of Code的一部分。请参见:model._meta.many_to_many
。 - Bernhard Vallantdjango/core/management/commands/loaddata.py
使用_meta来遍历应用程序、模型和字段的树形结构。这是一个不错的模式可以学习...而且你可以确定这是“官方方式”。 - hobs_meta.virtual_fields
。 - andrei1089_meta
现在是一个正式支持的API(Django 1.8中新增)。 - mgalgs我知道这篇文章很旧,但我想告诉那些正在寻找同样内容的人,有一个公共且官方的API可以实现这一点:get_fields()
和get_field()
用法:
fields = model._meta.get_fields()
my_field = model._meta.get_field('my_field')
https://docs.djangoproject.com/en/3.2/ref/models/meta/#retrieving-all-field-instances-of-a-model
get_fields()
https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields - RisadinhaNamedTuple
的 _replace
一样,下划线是为了防止命名冲突,而不是表示它是私有的。如果你有一个 meta
字段,就会发生冲突。 - Carcigenicateget_fields()
返回一个元组,每个元素都是一个 Model field
类型,不能直接用作字符串。所以,field.name
将返回字段名称。
my_model_fields = [field.name for field in MyModel._meta.get_fields()]
上面的代码将返回一个包含所有字段名称的列表。
示例
In [11]: from django.contrib.auth.models import User
In [12]: User._meta.get_fields()
Out[12]:
(<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>)
In [13]: [field.name for field in User._meta.get_fields()]
Out[13]:
['logentry',
'id',
'password',
'last_login',
'is_superuser',
'username',
'first_name',
'last_name',
'email',
'is_staff',
'is_active',
'date_joined',
'groups',
'user_permissions']
现在有一种特殊的方法 - get_fields()
>>> from django.contrib.auth.models import User
>>> User._meta.get_fields()
它接受两个参数,可用于控制返回哪些字段:
include_parents
默认为True。递归包括在父类上定义的字段。如果设置为False,则get_fields()将仅搜索当前模型直接声明的字段。从抽象模型或代理类直接继承的模型中的字段被认为是本地字段,不在父级上。
include_hidden
默认为False。如果设置为True,则get_fields()将包括用于支持其他字段功能的字段。这还将包括任何具有以“+”开头的related_name(例如ManyToManyField或ForeignKey)的字段。
fields = [f"{f.name}_id" if f.is_relation else f.name for f in model._meta.fields]
这是 Django 本身从模型构建表单时所进行的操作。它使用 _meta 属性,但正如 Bernhard 所指出的那样,它同时使用了 _meta.fields 和 _meta.many_to_many。通过查看 django.forms.models.fields_for_model,您可以这样做:
opts = model._meta
for f in sorted(opts.fields + opts.many_to_many):
print '%s: %s' % (f.name, f)
_meta中包含的模型字段在多个位置以相应字段对象的列表形式列出。将它们作为字典处理并使用字段名称作为键可能更容易操作。
在我看来,这是收集和组织模型字段对象的最简洁和最具表现力方式:
def get_model_fields(model):
fields = {}
options = model._meta
for field in sorted(options.concrete_fields + options.many_to_many + options.virtual_fields):
fields[field.name] = field
return fields
fields = Model._meta.fields
Model._meta.get_fields()
获取单个字段:Model._meta.get_field('字段名')
例如:Session._meta.get_field('expire_date')
"最初的回答"ModelAdmin.get_fields
方法(docs),它返回一个字段名称字符串list
。class MyModelAdmin(admin.ModelAdmin):
# extending change_view, just as an example
def change_view(self, request, object_id=None, form_url='', extra_context=None):
# get the model field names
field_names = self.get_fields(request)
# use the field names
...