如何在Django中内省属性和模型字段?

时间:2011-02-08 07:00:00

标签: python django models

我正在尝试获取给定对象的所有现有模型字段和属性的列表。是否有一种干净的方式来检查一个物体,以便我可以得到一个字段和属性的字典。

class MyModel(Model)
    url = models.TextField()

    def _get_location(self):
        return "%s/jobs/%d"%(url, self.id)

    location = property(_get_location)

我想要的是返回一个看起来像这样的字典:

{
  'id' : 1,
  'url':'http://foo',
  'location' : 'http://foo/jobs/1'
}   

我可以使用model._meta.fields来获取模型字段,但这不会给我属性但不是真正的数据库字段。

4 个答案:

答案 0 :(得分:10)

如果您只想要模型字段和属性(使用属性声明的那些),那么:

def get_fields_and_properties(model, instance):
    field_names = [f.name for f in model._meta.fields]
    property_names = [name for name in dir(model) if isinstance(getattr(model, name), property)]
    return dict((name, getattr(instance, name)) for name in field_names + property_names)

instance = MyModel()
print get_fields_and_properties(MyModel, instance)

这里唯一的一点就是通过来查找与属性描述符对应的字段。通过类访问它们会给出描述符,而通过实例,它会为您提供值。

答案 1 :(得分:1)

麻烦的是你说你只想要字段,但是通过将属性投入混合来使事情变得复杂。 Python中没有任何简单的方法可以区分属性和任何其他随机方法。这与Django没有任何关系:它只是一个属性只是一个通过描述符访问的方法。因为类中的任何数量的东西也都是描述符,所以你很难区分它们。

您是否有任何理由无法在包含所需属性的类级别定义列表,那么只需在每个元素上调用getattr

答案 2 :(得分:0)

您应该在实例上使用dir()函数。跳过以'__'开头的内容,而不是使用getattr从您的实例中获取值。

properties = [prop for prop in dir(SomeClass) if not prop.startswith("__")]

obj = {}
for prop in properties:
    obj[prop] = getattr(myinstance, prop)

答案 3 :(得分:0)

class Awesome(models.Model):
 foo = models.TextField()
 bar = models.CharField(max_length = 200)

awe = Awesome()
for property in awe.__dict__.copy():
 # pass private properties.
 if not property.startswith('_'):
  print property,getattr(awe,property)

这就是他们在Django中的表现。