Django:获取模型字段列表?

时间:2010-06-23 23:29:30

标签: django django-models

我已经定义了一个User类,它最终继承自models.Model。我想获得为此模型定义的所有字段的列表。例如,phone_number = CharField(max_length=20)。基本上,我想要检索从Field类继承的任何内容。

我以为我可以利用inspect.getmembers(model)检索这些内容,但它返回的列表不包含任何这些字段。看起来Django已经掌握了这个类,并添加了所有的魔法属性,并删除了实际定义的内容。那么......我怎样才能获得这些领域?它们可能具有为自己的内部目的检索它们的功能吗?

13 个答案:

答案 0 :(得分:269)

Django 1.8及更高版本:

您应该使用get_fields()

[f.name for f in MyModel._meta.get_fields()]

get_all_field_names()方法为deprecated starting from Django 1.8 and will be removed in 1.10

上面链接的文档页面提供了get_all_field_names()的完全向后兼容的实现,但是对于大多数用途,前面的示例应该可以正常工作。


1.8之前的Django版本:

model._meta.get_all_field_names()

这应该可以解决问题。

这需要一个实际的模型实例。如果你拥有的只是django.db.models.Model的子类,那么你应该调用myproject.myapp.models.MyModel._meta.get_all_field_names()

答案 1 :(得分:69)

此处提到的get_all_related_fields()方法已deprecated in 1.8。从现在开始get_fields()

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

答案 2 :(得分:52)

我发现将此添加到django模型非常有用:

def __iter__(self):
    for field_name in self._meta.get_all_field_names():
        value = getattr(self, field_name, None)
        yield (field_name, value)

这可以让你:

for field, val in object:
    print field, val

答案 3 :(得分:11)

这就是诀窍。我只在Django 1.7中测试它。

your_fields = YourModel._meta.local_fields
your_field_names = [f.name for f in your_fields]

Model._meta.local_fields不包含多对多字段。你应该使用Model._meta.local_many_to_many来获取它们。

答案 4 :(得分:10)

def __iter__(self):
    field_names = [f.name for f in self._meta.fields]
    for field_name in field_names:
        value = getattr(self, field_name, None)
        yield (field_name, value)

这在django==1.11.8

中对我有用

答案 5 :(得分:7)

MyModel._meta.get_all_field_names() 已弃用多个版本,Django 1.10中已移除

以下是向后兼容的建议from the docs

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

答案 6 :(得分:6)

目前尚不清楚您是否有类的实例或类本身并尝试检索字段,但不管怎样,请考虑以下代码

使用实例

instance = User.objects.get(username="foo")
instance.__dict__ # returns a dictionary with all fields and their values
instance.__dict__.keys() # returns a dictionary with all fields
list(instance.__dict__.keys()) # returns list with all fields

使用课程

User._meta.__dict__.get("fields") # returns the fields

# to get the field names consider looping over the fields and calling __str__()
for field in User._meta.__dict__.get("fields"):
    field.__str__() # e.g. 'auth.User.id'

答案 7 :(得分:6)

由于大多数答案已过时,因此我将尝试在 Django 2.2 上进行更新 在这里发布-您的应用(发布,博客,商店等)

1)通过模型链接:https://docs.djangoproject.com/en/2.2/ref/models/meta/

from posts.model import BlogPost

all_fields = BlogPost._meta.fields
#or
all_fields = BlogPost._meta.get_fields()

请注意:

all_fields=BlogPost._meta.get_fields()

还将获得一些关系,例如。您无法在视图中显示。
就我而言:

Organisation._meta.fields
(<django.db.models.fields.AutoField: id>, <django.db.models.fields.DateField: created>...

Organisation._meta.get_fields()
(<ManyToOneRel: crm.activity>, <django.db.models.fields.AutoField: id>, <django.db.models.fields.DateField: created>...

2)从实例

from posts.model import BlogPost

bp = BlogPost()
all_fields = BlogPost._meta.fields

3)来自父模型

假设我们将Post作为父模型,并且您希望查看列表中的所有字段,并且在Edit模式下将父字段设为只读。

from django.contrib import admin
from posts.model import BlogPost 




@admin.register(BlogPost)
class BlogPost(admin.ModelAdmin):
    all_fields = [f.name for f Organisation._meta.fields]
    parent_fields = BlogPost.get_deferred_fields(BlogPost)

    list_display = all_fields
    read_only = parent_fields

答案 8 :(得分:5)

添加,我使用自我对象,这对我有用:

[f.name for f in self.model._meta.get_fields()]

答案 9 :(得分:4)

至少使用Django 1.9.9 - 我目前正在使用的版本 - ,请注意.get_fields()实际上也是&#34;考虑&#34;任何外国模型作为一个领域,这可能是有问题的。说你有:

class Parent(models.Model):
    id = UUIDField(primary_key=True)

class Child(models.Model):
    parent = models.ForeignKey(Parent)

接着是

>>> map(lambda field:field.name, Parent._model._meta.get_fields())
['id', 'child']

while,如@Rockallite所示

>>> map(lambda field:field.name, Parent._model._meta.local_fields)
['id']

答案 10 :(得分:4)

因此,在我找到这篇文章之前,我已经成功地找到了它。

Model._meta.fields

相同
Model._meta.get_fields()

我不确定结果是否有区别。我运行了此循环并获得了相同的输出。

for field in Model._meta.fields:
    print(field.name)

答案 11 :(得分:0)

有时我们也需要db列:

def get_db_field_names(instance):
   your_fields = instance._meta.local_fields
   db_field_names=[f.name+'_id' if f.related_model is not None else f.name  for f in your_fields]
   model_field_names = [f.name for f in your_fields]
   return db_field_names,model_field_names

调用方法以获取字段:

db_field_names,model_field_names=get_db_field_names(Mymodel)

答案 12 :(得分:-1)

为什么不仅仅使用它:

manage.py inspectdb

示例输出:

class GuardianUserobjectpermission(models.Model):
    id = models.IntegerField(primary_key=True)  # AutoField?
    object_pk = models.CharField(max_length=255)
    content_type = models.ForeignKey(DjangoContentType, models.DO_NOTHING)
    permission = models.ForeignKey(AuthPermission, models.DO_NOTHING)
    user = models.ForeignKey(CustomUsers, models.DO_NOTHING)

    class Meta:
        managed = False
        db_table = 'guardian_userobjectpermission'
        unique_together = (('user', 'permission', 'object_pk'),)