Django:为什么Django模型字段的类属性?

时间:2011-05-10 00:18:58

标签: python django django-models

在Django中,模型的字段被定义为类属性。

这意味着模型的所有实例都会为这些字段共享相同的值,不是吗?

说我有模特

class Tag(models.Model):
    name = models.CharField(max_length=30)

我有一个用户可以提交标签的表单。假设用户提交了2个标签:“Python”和“Django”。如果我在视图中创建了2个Tag实例:

t1 = Tag(name="Python")
t2 = Tag(name="Django")

由于name是一个类属性,t1t2不应该name具有相同的值,在这种情况下应该是“Django”?

但实际上name的行为类似于实例属性,而不是类属性。你能解释一下发生了什么吗?

1 个答案:

答案 0 :(得分:18)

不,原因与此相同:

>>> class Foo(object):
...     bar = 'Foo attribute'
...
>>> f = Foo()
>>> f.bar
'Foo attribute'
>>> Foo.bar
'Foo attribute'
>>> f.bar = 'instance attribute'
>>> f.bar
'instance attribute'
>>> Foo.bar
'Foo attribute'

为对象分配属性时,对象的“类别”属性将被对象“重叠”。但是,在属性查找中,如果有问题的对象没有定义所述属性,则将返回第一类。

在Django中,ORM层使用这些类属性来生成转换为SQL查询和操作的机制(深层,元类魔法在幕后进行)。

编辑:回答您的问题 -

要理解这一点,您需要了解一下Python的data model。实质上,类和对象都有名称空间。如果您查看其特殊的__dict__属性,这一点很明显:

>>> print Foo.__dict__
{'__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute
'__weakref__' of 'Foo' objects>, '__module__': '__main__', 'bar': 'Foo attribute
', '__doc__': None}
>>> f = Foo()
>>> print f.__dict__
{}

首次创建对象f时,它具有空命名空间。当您查找f.bar时,会查找此命名空间(实际上是字典)。由于此处找不到'bar'属性,因此会查找f的类Foo。我们在那里找到'bar': 'Foo attribute'。这就是将要返回的内容:

>>> f.bar
'Foo attribute'

现在,当您为对象分配属性值,并且其名称空间中尚未存在所述属性名称时,它将被创建:

>>> f.bar = 'instance attribute'
>>> print f.__dict__
{'bar': 'instance attribute'}
>>> f.bar
'instance attribute'

现在,您知道下次f.bar被查找时会发生什么! f.__dict__['bar']存在,在我们查看Foo的命名空间之前将会返回。

当然,如果您的目的是始终访问和操作类的属性而不是实例,那么您需要使用类的名称。

>>> Foo.bar
'Foo attribute'
>>> Foo.__dict__['bar']
'Foo attribute'
相关问题