2016-09-16 81 views
3

我一直在阅读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的要在模型中的字段变量是静态的?

+0

关于如何在Pro Django中创建模型,Marty Alchin的第3章(模型),Apress –

回答

6

Django使用metaclass来创建模型类。就像一个类的__init__()方法创建一个新的实例一样,元类的__new__()方法自己创建类。所有在类中定义的变量,函数,属性等被传递给__new__()函数。严格地说,只是在类体中定义一个变量不会创建一个静态/类变量 - 只有当__new__()函数接收到变量并将其设置在类上时,它才会是类/静态变量。

通过提供自定义的__new__()方法,Django在字段和特殊的Meta内部类中覆盖了此行为。内层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,但这将是实际的字段实例,而不是相关的数据库值。基本上你会错过使模型成为模型的魔力。

相关问题