Django - 为什么在Model Classes Static

时间:2016-09-16 19:27:32

标签: python django

我一直在阅读和使用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希望模型中的字段变量是静态的感到困惑?

1 个答案:

答案 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.fieldsAlbum的实例具有artists属性,但这不是字段。相反,它是与该字段相关的数据库值。模型的__init__方法使用self._meta.fields使用传递给__init__的值或使用默认值填充任何属性,以确保实例变量存在。

只有类变量传递给__new__方法。如果要在__init__中将字段定义为实例变量,则该字段永远不会传递给Model._meta.fields,而Django根本不知道该字段。您将能够访问Album.artist,但这将是实际的字段实例,而不是相关的数据库值。基本上你会错过将模型变成模型的魔力。