使用字符串而不是点语法访问Django模型的字段?


77

在Django中,我可以这样做:

test = Test.objects.get(id=1)
test.name

我希望能够使用动态生成的字符串访问属性,如下所示:

test['name']

或任何其他使用字符串的语法。我试过了

test._meta.get_field_by_name('name')

但这会返回字段本身而不是值。

有任何想法吗?

Answers:


111

您可以使用python的内置getattr()函数:

getattr(test, 'name')

2
一分钟太慢了!不应该花时间测试一下;)
卡斯帕(Caspar

2
啊,我什至不必使用Django功能,而且我学到了一些关于Python的新知识。谢谢您的帮助。
davidscolgan '02

适用于ForeignKey吗?
Giancarlo Ventura,

谁知道我们在内部类方法中如何称其为Model .... self.getattr(SelfModelName, 'id')= =?
Micheal J. Roberts,

有点晚了,但是您可以使用getattr(self,'id')
Brouwer


12

其他答案仍然有效,但是现在您可以使用Django的_meta.get_field()进行此操作。

test._meta.get_field('name')

请注意,Model _meta API从1.8开始就已开始提供官方支持和文档,但在其官方文档发布之前已在以前的版本中分发和使用。


2
这仍然返回该字段本身,并且OP对该字段的值感兴趣。
rob3c

6

在Python中,通常可以访问具有dict方法的对象内的值。

假设您有这个课程:

class Dog(object):
    def __init___(self, color):
        self.color = color

然后我实例化它:

dog = Dog('brown')

所以我可以通过以下方式查看颜色:

print dog.color

我还可以通过执行以下操作来查看颜色:

print dog.__dict__['color']

我可以设置颜色:

print dog.__dict__['color'] = 'green'

print dog.color

>>>green

1
它将起作用,但是通常,如果可能的话,您要避免使用带下划线的属性/方法。这表明它们不稳定(随时可能被完全删除或固有地更改,没有任何警告),或者由于某些其他原因不打算成为公共接口的一部分。有时您必须(但在这种情况下)getattr可以使用,因此是正确的选择。
克里斯·普拉特

@ChrisPratt单下划线,双下划线和双下划线与后跟双下划线之间是有区别的。尽管您所说的(或多或少)适用于前两者,但该方法暗示它是内置的,并且不表示任何隐私或保护,以及通常在其中进行操作符重载和初始化的位置。docs.python.org/reference/datamodel.html#specialnames siafoo.net/article/57 stackoverflow.com/questions/1301346/...
ashwoods

1
@ashwoods:是的,但是即使那样,它们的使用通常也包含另一个类中,因此它是一种使用内部代码情况的内部代码。最终,通常您不会仅在仍将特定实现与“ public”接口相去甚远的其他类中狂野地使用此类方法。
克里斯·普拉特

@ChrisPratt,这在当时还算是学术性的,但是如果您在第二版Nutshell中引用Python的第84页,他将描述这种行为。他说:“在类主体中创建的类属性,通过分配属性在主体外部创建的属性或通过显式绑定C .__ dict__的条目在主体外部创建的属性都没有区别。也就是说,我同意getattr可能是正确的解决方案在这种情况下,但这并不意味着不能使用dict内部的类主体外部,或任何其他双下划线方法
James R
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.