如何在Django中自省属性和模型字段?
我想获取一个对象中所有现有的模型字段和属性的列表。有没有简单的方法可以检查一个对象,以便我能得到一个字段和属性的字典。
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
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中是怎么做的。
1
问题在于,你说你只想要字段,但又把属性扔进来了,这就让事情变得复杂了。在Python中,其实没有简单的方法来区分一个属性和其他普通的方法。这跟Django没有关系:属性其实就是通过描述符访问的方法。因为类里面的很多东西也会是描述符,所以你会很难区分它们。
有没有什么理由让你不能在类里面定义一个列表,把你想要的所有属性都放进去,然后对每个元素调用 getattr
呢?
18
如果你只想要模型中的字段和属性(那些用属性声明的),那么可以这样做:
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)
这里唯一多出来的部分是要遍历一下 class,找出和属性描述符对应的字段。通过类来访问这些字段会得到描述符,而通过实例访问则会得到实际的值。