在Django中获取模型的字段

时间:2010-09-05 21:06:09

标签: django django-models introspection metamodel

鉴于Django模型,我试图列出其所有字段。我已经看到了一些使用_meta模型属性执行此操作的示例,但是meta前面的下划线是否表示_meta属性是私有属性,不应该直接访问? ...例如,因为_meta的布局将来可能会改变而不是一个稳定的API?

_meta是这个规则的例外吗?它是否稳定并且可以使用,或者它被认为是不好的做法?或者是否有一个函数或其他方法来反省模型的字段而不使用_meta属性?下面是一些链接列表,显示如何使用_meta属性

执行此操作

非常感谢任何建议。

django object get/set field

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

How to introspect django model fields?

10 个答案:

答案 0 :(得分:130)

_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的一部分。请参阅:
- https://groups.google.com/forum/#!topic/django-developers/hD4roZq0wyk
- https://code.djangoproject.com/wiki/new_meta_api

答案 1 :(得分:82)

我知道这篇文章很老了,但我只是想告诉那些正在搜索相同内容的人,有公共和官方的API来执行此操作:get_fields()get_field()

用法:

fields = model._meta.get_fields()
my_field = model._meta.get_field('my_field')

https://docs.djangoproject.com/en/1.8/ref/models/meta/

答案 2 :(得分:8)

这是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)

答案 3 :(得分:5)

现在有一种特殊方法 - get_fields()

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

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

  • <强> include_parents

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

  • <强> include_hidden

    默认为假。如果设置为True,则get_fields()将包含用于支持其他字段功能的字段。这还将包括具有以“+”开头的related_name(例如ManyToManyField或ForeignKey)的任何字段

答案 4 :(得分:4)

_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中的This example usage。)

答案 5 :(得分:4)

get_fields()返回一个tuple,每个元素都是一个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']

答案 6 :(得分:2)

这个怎么样。

List<JobInstance> jobInstance = jobExplorer.getJobInstances(job.getName(), 0, 1);
JobParameters jobParameters = new JobParameters();

if (!jobInstance.isEmpty()) {
    JobInstance lastInstance = jobInstance.get(0);
    List<JobExecution> jobExecutions = jobExplorer.get(lastInstance);
    jobParameters = jobExecutions.get(0).getJobParameters();
}

答案 7 :(得分:1)

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

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

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

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

答案 8 :(得分:0)

如果您的 admin 网站需要此方法,则还有ModelAdmin.get_fields方法(docs),该方法返回字段名称为{{ 1}}。

例如:

list

答案 9 :(得分:0)

另一种方法是将函数添加到模型中,当您要覆盖日期时可以调用该函数。

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