我一直在阅读和使用Django一段时间。我仍然困惑的一件事是为什么我们在Django中创建的模型类由静态变量而不是成员变量组成。例如
class Album(models.Model):
artist = models.CharField(max_length=128, unique=True)
title = models.CharField(max_length=128, unique=True)
genre = models.CharField(max_length=128, unique=True)
def __unicode__(self):
return self.name
我在这里阅读this页面解释了python中的静态变量和实例变量但是我仍然对为什么Django希望模型中的字段变量是静态的感到困惑?
答案 0 :(得分:8)
Django使用metaclass来创建模型类。就像一个类的__init__()
方法创建一个新实例一样,元类的__new__()
方法创建了类本身。类主体中定义的所有变量,函数,属性等都将传递给__new__()
函数。严格地说,只是在类体中定义变量不会创建静态/类变量 - 只有当__new__()
函数接收变量并将其设置在类上时,它才会是类/静态变量。
当涉及字段和特殊Meta
内部类时,Django会通过提供自定义__new__()
方法来覆盖此行为。内部Meta
类中的选项将转换为Options
实例,该实例将存储为Model._meta
而不是Model.Meta
。同样,您定义的任何字段都存储在Model._meta.fields
中,而不是存储在类/静态变量中。
您会注意到,在您的示例中,类Album
没有artist
属性:Album.artist
只会引发AttributeError
。这是因为元类将字段从类移动到Album._meta.fields
。 Album
的实例具有artists
属性,但这不是字段。相反,它是与该字段相关的数据库值。模型的__init__
方法使用self._meta.fields
使用传递给__init__
的值或使用默认值填充任何属性,以确保实例变量存在。
只有类变量传递给__new__
方法。如果要在__init__
中将字段定义为实例变量,则该字段永远不会传递给Model._meta.fields
,而Django根本不知道该字段。您将能够访问Album.artist
,但这将是实际的字段实例,而不是相关的数据库值。基本上你会错过将模型变成模型的魔力。