如何自省 Django 中的属性和模型字段?
Posted
技术标签:
【中文标题】如何自省 Django 中的属性和模型字段?【英文标题】:How can I introspect properties and model fields in Django? 【发布时间】:2011-06-23 06:11:59 【问题描述】:我正在尝试获取给定对象的所有现有模型字段和属性的列表。有没有一种干净的方法来内省对象,以便我可以获得字段和属性的字典。
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
来获取模型字段,但这并没有给我属性而不是真正的数据库字段。
【问题讨论】:
【参考方案1】:如果您只需要模型字段和属性(使用属性声明的),那么:
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 来查找对应于属性描述符的字段。通过类访问它们会得到描述符,而通过实例会得到值。
【讨论】:
谢谢 - 这正是我所需要的。我试图在实例中寻找“属性”类型的东西,但我应该在类中寻找它们。【参考方案2】:问题是你说你只想要字段,然后通过将属性混入其中使事情变得复杂。在 Python 中没有任何简单的方法可以区分属性和任何其他随机方法。这与 Django 没有任何关系:只是属性只是一个通过描述符访问的方法。因为类中的任意数量的事物也都是描述符,所以您很难区分它们。
有什么理由不能在类级别定义一个包含所有你想要的属性的列表,然后只对每个元素调用getattr
?
【讨论】:
【参考方案3】:您应该在您的实例上使用 dir() 函数。跳过以 '__' 开头的任何内容,然后使用 getattr 从您的实例中获取值。
properties = [prop for prop in dir(SomeClass) if not prop.startswith("__")]
obj =
for prop in properties:
obj[prop] = getattr(myinstance, prop)
【讨论】:
不适用于 Django 模型。对象还有很多其他可用的方法和变量(继承自基础 Django Model 类),但严格来说不是 Django 字段或属性。我需要能够区分属性/字段和其他东西。 澄清一下——我指的是内置的“属性”(adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin)——不仅仅是python对象的通用属性。 @shreddd:比较你所拥有的与 model._meta.fields 以区分数据库字段和属性。 对不起 - 我想你误解了这个问题。请参阅我正在寻找的答案的公认解决方案。事实证明,不知道实例中是否有“属性”类型的东西——你需要检查类。【参考方案4】: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 中的做法。
【讨论】:
这让我得到了字典中的所有东西,但不是使用 property() 声明的东西。看起来我需要直接从 Model 类中提取它。请参阅上面 John Montgomery 的解决方案。以上是关于如何自省 Django 中的属性和模型字段?的主要内容,如果未能解决你的问题,请参考以下文章
计算机程序中的自省程序(反射程序)(introspective program)是什么?(introspectableintrospection)