拿到 Django 的模型田

给定一个 Django 模型,我尝试列出它的所有字段。我看到过一些使用 _ meta 模型属性的例子,但是 meta 前面的下划线不是表示 _ meta 属性是私有属性,不应该直接访问吗?... 因为,例如,_ meta 的布局可能在未来发生变化,而不是一个稳定的 API?

_ meta 是这条规则的例外吗?它是稳定的并且可以使用,还是访问它被认为是不好的做法?或者有没有一个函数或者其他方法可以在不使用 _ meta 属性的情况下自省模型的字段?下面是一些链接的列表,展示了如何使用 _ meta 属性实现这一点

非常感谢你的建议。

Django 对象 get/set 字段

Http://www.djangofoo.com/80/get-list-model-fields

如何自省 django 模型字段?

171192 次浏览

_meta是私有的,但相对稳定。目前正在努力将其正式化,编制文档,并删除下划线,这可能发生在1.3或1.4之前。我想人们会努力确保这些东西向后兼容,因为很多人已经在使用它了。

如果您特别关心兼容性,那么编写一个接受模型并返回字段的函数。这意味着如果将来某些事情发生了变化,您只需要改变一个函数。

def get_model_fields(model):
return model._meta.fields

我相信这将返回 Field对象的列表。要从实例中获取每个字段的值,请使用 getattr(instance, field.name)

更新: Django 贡献者正在开发一个 API 来替换 _ Meta 对象,作为 Google“代码之夏”的一部分。参见:
译自: 美国《 https://groups.google.com/forum/#!topic/django-developers/hd4rozq0wyk 》杂志网站(ref)原文地址: http://groups.google.com/forum/# ! subject/django-developers/hD4roZq0wyk
译自: 美国《科学》杂志网站(https://code.djangoproject.com/wiki/new _ meta _ api) https://code.djangoproject.com/wiki/new_meta_api

这是 Django 在从模型构建表单时自己完成的任务。它使用了 _ meta 属性,但是正如 Bernhard 指出的,它同时使用了 _ meta.fields 和 _ met.many _ to _ many。查看 django.forms.mods.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

(请参见 django.forms.mods.fields _ for _ model 中的 这个例子的用法。)

我知道这篇文章已经很老了,但是我只是想告诉那些正在搜索相同内容的人,有一个公共的和官方的 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

这个怎么样。

fields = Model._meta.fields

现在有一种特殊的方法-Get _ fields ()

    >>> from django.contrib.auth.models import User
>>> User._meta.get_fields()

它接受两个参数,可用于控制返回哪些字段:

  • 包括 _ 家长

    默认为真。递归地包括在父类上定义的字段。如果设置为 False,get _ fields ()将只搜索直接在当前模型上声明的字段。直接从抽象模型或代理类继承的模型的字段被认为是本地的,而不是在父类上。

  • Include _ hide

    默认为假。如果设置为 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()]
上面的代码将返回一个包含所有字段名的列表

示例 < br >

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']

如果您的 管理员站点需要它,还有一个 ModelAdmin.get_fields方法(医生) ,它返回字段名为 stringslist

例如:

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
...

根据 django 文档2.2,您可以使用:

获取所有字段: Model._meta.get_fields()

获取单个字段: Model._meta.get_field('field name')

例如 Session._meta.get_field('expire_date')

另一种方法是向模型中添加函数,当您希望重写日期时,可以调用该函数。

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()

fields = [f"{f.name}_id" if f.is_relation else f.name for f in model._meta.fields]