得到的名单:Django模型的领域?

Django: Get list of model fields?

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

我想我可以利用inspect.getmembers(model)来检索这些字段,但它返回的列表中不包含任何这些字段。看起来Django已经获得了这个类的控制权,并添加了它所有的魔法属性,并去掉了实际定义的内容。所以…我怎样才能得到这些田地?它们可能有一个函数来检索它们以用于内部目的?


Django 1.8及更高版本:

您应该使用get_fields()

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

从Django开始,不推荐使用get_all_field_names()方法。1.8,将在1.10中删除。

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

1.8之前的Django版本:

1
model._meta.get_all_field_names()

这应该能解决问题。

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


本文提到的get_all_related_fields()方法在1.8中已被弃用。从现在起,它是get_fields()

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


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

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

这样可以做到:

1
2
for field, val in object:
    print field, val


这就是窍门。我只在姜戈1.7测试它。

1
2
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来获取它们。


1
2
3
4
5
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)

这对我在江户很有用。


MyModel._meta.get_all_field_names()被否决了,在django 1.10中有几个版本被删除。

以下是来自文档的向后兼容建议:

1
2
3
4
5
6
7
8
9
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)
)))


尚不清楚您是否有类的实例或类本身,并尝试检索字段,但无论哪种方法,都要考虑以下代码

使用实例

1
2
3
4
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

使用类

1
2
3
4
5
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'

另外,我使用的是自我对象,这对我很有用:

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

所以在我找到这篇文章之前,我成功地找到了这篇文章。

1
Model._meta.fields

它的工作原理与

1
Model._meta.get_fields()

我不知道结果有什么区别,如果有。我运行了这个循环,得到了相同的输出。

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

至少对于django 1.9.9——我目前使用的版本——来说,请注意,.get_fields()实际上也"将"任何外国模型视为一个领域,这可能有问题。说你有:

1
2
3
4
5
class Parent(models.Model):
    id = UUIDField(primary_key=True)

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

随之而来的是

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

同时,如@rockallite所示

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

为什么不使用它呢?

1
manage.py inspectdb

实例输出:

1
2
3
4
5
6
7
8
9
10
11
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'),)