给定Django模型,我试图列出其所有字段。我已经看到了使用_meta模型属性执行此操作的一些示例,但是meta前面的下划线是否表示_meta属性是私有属性,不应直接访问?...例如,因为_meta的布局将来可能会更改,并且不是稳定的API?
_meta是该规则的例外吗?它是否稳定且可以立即使用,还是访问它的不良做法?还是有一种功能或某种其他方法可以在不使用_meta属性的情况下对模型的字段进行内部检查?以下是一些链接的列表,这些链接显示了如何使用_meta属性执行此操作
任何建议深表感谢。
给定Django模型,我试图列出其所有字段。我已经看到了使用_meta模型属性执行此操作的一些示例,但是meta前面的下划线是否表示_meta属性是私有属性,不应直接访问?...例如,因为_meta的布局将来可能会更改,并且不是稳定的API?
_meta是该规则的例外吗?它是否稳定且可以立即使用,还是访问它的不良做法?还是有一种功能或某种其他方法可以在不使用_meta属性的情况下对模型的字段进行内部检查?以下是一些链接的列表,这些链接显示了如何使用_meta属性执行此操作
任何建议深表感谢。
Answers:
_meta是私有的,但相对稳定。我们正在努力对其进行形式化,记录和删除下划线,这可能在1.3或1.4之前发生。我想将会做出努力来确保事物向后兼容,因为无论如何还是有很多人在使用它。
如果您特别关注兼容性,请编写一个采用模型并返回字段的函数。这意味着,如果将来发生某些变化,则只需更改一个功能。
def get_model_fields(model):
return model._meta.fields
我相信这将返回Field对象列表。要从实例获取每个字段的值,请使用getattr(instance, field.name)。
更新:作为Google Summer of Code的一部分,Django贡献者正在开发一个API来替换_Meta对象。请参阅:-https : //groups.google.com/forum/#
! topic
/ django
- developers / hD4roZq0wyk - https : //code.djangoproject.com/wiki/new_meta_api
model._meta.many_to_many!
django/core/management/commands/loaddata.py使用_meta遍历应用程序,模型和字段的树。可以遵循的好模式...您可以打赌,这是“官方方式”。
_meta.virtual_fields
_meta现在是正式的,受支持的API(Django 1.8中的新增功能)
我知道这个职位是很老,但我只在乎告诉任何人谁是寻找有一个公众和官方的API做这同样的事情:get_fields()和get_field()
用法:
fields = model._meta.get_fields()
my_field = model._meta.get_field('my_field')
get_fields() docs.djangoproject.com/en/1.10/ref/models/meta/...
_meta?
现在有一个特殊的方法-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)
get_fields()返回一个tuple,每个元素都是一个Model field类型,不能直接用作字符串。因此,field.name将返回字段名称
my_model_fields = [field.name for field in MyModel._meta.get_fields()]
上面的代码将返回一个列表conatining所有字段名称
示例
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']
_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
(请参阅django.forms.models.fields_for_model中的此示例用法。)
根据django文档2.2,您可以使用:
要获取所有字段: Model._meta.get_fields()
要获取单个字段: Model._meta.get_field('field name')
例如 Session._meta.get_field('expire_date')
如果您的管理网站需要此ModelAdmin.get_fields方法,则还有方法(docs),该方法返回list字段名称strings。
例如:
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
...
另一种方法是将函数添加到模型中,当您要覆盖日期时可以调用该函数。
class MyModel(models.Model):
name = models.CharField(max_length=256)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
def set_created_date(self, created_date):
field = self._meta.get_field('created')
field.auto_now_add = False
self.created = created_date
def set_modified_date(self, modified_date):
field = self._meta.get_field('modified')
field.auto_now = False
self.modified = modified_date
my_model = MyModel(name='test')
my_model.set_modified_date(new_date)
my_model.set_created_date(new_date)
my_model.save()