首页 文章

Django:获取模型字段列表?

提问于
浏览
140

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

我以为我能够通过利用 inspect.getmembers(model) 来检索这些,但它返回的列表实际上已经定义了't contain any of these fields. It looks like Django has already gotten a hold of the class and added all its magic attributes and stripped out what' . 那么......我怎样才能获得这些领域?它们可能具有为自己的内部目的检索它们的功能吗?

10 回答

  • 243

    对于Django 1.8及更高版本:

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

    上面链接的文档页面提供了 get_all_field_names() 的完全向后兼容的实现,但是对于大多数用途 [f.name for f in MyModel._meta.get_fields()] 应该可以正常工作 .

    对于1.8之前的Django版本:

    model._meta.get_all_field_names()
    

    这应该够了吧 .

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

  • 3

    这里提到的 get_all_related_fields() 方法已经deprecated in 1.8 . 从现在开始它是get_fields() .

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

    我发现将这个添加到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
    
  • 9

    这样就可以了 . 我只在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 获取它们 .

  • 8
    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

  • 2

    MyModel._meta.get_all_field_names()deprecated 几个版本和Django 1.10中的 removed .

    这是向后兼容的建议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)
    )))
    
  • -1

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

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

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

    Using an instance

    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
    

    Using a class

    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'
    
  • 50

    至少有Django 1.9.9 - 我目前使用的版本 - ,请注意 .get_fields() 实际上也是"considers"任何外国模型作为字段,这可能有问题 . 说你有:

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

    而如@Rockallite所示

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

    为什么不使用它:

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

相关问题