2016-09-16 117 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,但這將是實際的字段實例,而不是相關的數據庫值。基本上你會錯過使模型成爲模型的魔力。

相關問題