Con*_*ion 15 python django django-models
在Django中,模型的字段被定义为类属性.
那么这意味着模型的所有实例都会为这些字段共享相同的值,不是吗?
说我有一个模特
class Tag(models.Model):
name = models.CharField(max_length=30)
Run Code Online (Sandbox Code Playgroud)
我有一个表单,用户可以在其中提交标签.假设用户提交了2个标签:"Python"和"Django".如果我在视图中创建了2个Tag实例:
t1 = Tag(name="Python")
t2 = Tag(name="Django")
Run Code Online (Sandbox Code Playgroud)
既然name
是一个类属性不应该都t1
和t2
有相同的值name
,在这种情况下,应该是"Django的"?
但实际上name
行为类似于实例属性而不是类属性.你能解释一下发生了什么吗?
San*_*nta 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'
Run Code Online (Sandbox Code Playgroud)
为对象分配属性时,对象的"类"属性将被对象"黯然失色".但是,在属性查找中,如果相关对象未定义所述属性,则将返回第一类.
在Django中,ORM层使用这些类属性来生成转换为SQL查询和操作的机制(深层,元类魔法在幕后进行).
编辑:回答你的问题 -
要理解这一点,您需要了解一下Python的数据模型.实质上,类和对象都有名称空间.如果您查看其特殊__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__
{}
Run Code Online (Sandbox Code Playgroud)
f
首次创建对象时,它具有空命名空间.当您进行查找时,会查找f.bar
此命名空间(实际上是字典).由于没有'bar'
发现有属性f
的类Foo
,在抬头.我们找到了'bar': 'Foo attribute'
.这就是将要返回的内容:
>>> f.bar
'Foo attribute'
Run Code Online (Sandbox Code Playgroud)
现在,当您为对象分配属性值,并且其名称空间中尚未存在所述属性名称时,将创建它:
>>> f.bar = 'instance attribute'
>>> print f.__dict__
{'bar': 'instance attribute'}
>>> f.bar
'instance attribute'
Run Code Online (Sandbox Code Playgroud)
现在,你知道下次f.bar
查找会发生什么!f.__dict__['bar']
存在并将在我们查看Foo
命名空间之前返回.
当然,如果您的目的是始终访问和操作类的属性而不是实例,则需要使用类的名称.
>>> Foo.bar
'Foo attribute'
>>> Foo.__dict__['bar']
'Foo attribute'
Run Code Online (Sandbox Code Playgroud)