摘要:在里寫一個數據庫驅動的應用的第一步是定義模型,也就是數據庫結構設計和附加的其它元數據。模型元數據是任何不是字段的東西,例如排序選項數據庫表名單數和復數名稱和。
Django 框架主要關注的是模型(Model)、模板(Template)和視圖(Views),稱為MTV模式。
它們各自的職責如下:
層次 | 職責 |
---|---|
模型(Model),即數據存取層 | 處理與數據相關的所有事務: 如何存取、如何驗證有效性、包含哪些行為以及數據之間的關系等。 |
模板(Template),即業務邏輯層 | 處理與表現相關的決定: 如何在頁面或其他類型文檔中進行顯示。 |
視圖(View),即表現層 | 存取模型及調取恰當模板的相關邏輯。模型與模板的橋梁。 |
簡單來說就是Model存取數據,View決定需要調取哪些數據,而Template則負責將調取出的數據以合理的方式展現出來。
在 Django 里寫一個數據庫驅動的 Web 應用的第一步是定義模型Model,也就是數據庫結構設計和附加的其它元數據。
模型包含了儲存的數據所必要的字段和行為。Django 的目標是你只需要定義數據模型,其它的雜七雜八代碼你都不用關心,它們會自動從模型生成。
所以讓我們首先搞定Model。
編寫Model.py如前面所講,Django中通常一個模型(Model)映射一個數據庫,處理與數據相關的事務。
對博客網站來說,最重要的數據就是文章。所以首先來建立一個存放文章的數據模型。
打開article/models.py文件,輸入如下代碼:
article/models.py from django.db import models # 導入內建的User模型。 from django.contrib.auth.models import User # timezone 用于處理時間相關事務。 from django.utils import timezone # 博客文章數據模型 class ArticlePost(models.Model): # 文章作者。參數 on_delete 用于指定數據刪除的方式,避免兩個關聯表的數據不一致。 author = models.ForeignKey(User, on_delete=models.CASCADE) # 文章標題。models.CharField 為字符串字段,用于保存較短的字符串,比如標題 title = models.CharField(max_length=100) # 文章正文。保存大量文本使用 TextField body = models.TextField() # 文章創建時間。參數 default=timezone.now 指定其在創建數據時將默認寫入當前的時間 created = models.DateTimeField(default=timezone.now) # 文章更新時間。參數 auto_now=True 指定每次數據更新時自動寫入當前時間 updated = models.DateTimeField(auto_now=True)
代碼非常直白。每個模型被表示為 django.db.models.Model 類的子類。每個模型有一些類變量,它們都表示模型里的一個數據庫字段。
每個字段都是 Field 類的實例 。比如字符字段被表示為 CharField ,日期時間字段被表示為 DateTimeField。這將告訴 Django 每個字段要處理的數據類型。
定義某些 Field 類實例需要參數。例如 CharField 需要一個 max_length參數。這個參數的用處不止于用來定義數據庫結構,也用于驗證數據。
使用 ForeignKey定義一個關系。這將告訴 Django,每個(或多個) ArticlePost 對象都關聯到一個 User 對象。Django本身具有一個簡單完整的賬號系統(User),足以滿足一般網站的賬號申請、建立、權限、群組等基本功能。
ArticlePost類定義了一篇文章所必須具備的要素:作者、標題、正文、創建時間以及更新時間。我們還可以額外再定義一些內容,規范ArticlePost中數據的行為。加入以下代碼:
article/models.py ... class ArticlePost(models.Model): ... # 內部類 class Meta 用于給 model 定義元數據 class Meta: # ordering 指定模型返回的數據的排列順序 # "-created" 表明數據應該以倒序排列 ordering = ("-created",) # 函數 __str__ 定義當調用對象的 str() 方法時的返回值內容 def __str__(self): # return self.title 將文章標題返回 return self.title
內部類Meta中的ordering定義了數據的排列方式。-created表示將以創建時間的倒序排列,保證了最新的文章總是在網頁的最上方。注意ordering是元組,括號中只含一個元素時不要忘記末尾的逗號。
__str__方法定義了需要表示數據時應該顯示的名稱。給模型增加 __str__方法是很重要的,它最常見的就是在Django管理后臺中做為對象的顯示值。因此應該總是返回一個友好易讀的字符串。后面會看到它的好處。
整理并去掉注釋,全部代碼放在一起是這樣:
article/models.py from django.db import models from django.contrib.auth.models import User from django.utils import timezone class ArticlePost(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) title = models.CharField(max_length=100) body = models.TextField() created = models.DateTimeField(default=timezone.now) updated = models.DateTimeField(auto_now=True) class Meta: ordering = ("-created",) def __str__(self): return self.title
恭喜你,你已經完成了博客網站最核心的數據模型的大部分內容。
代碼不到20行,是不是完全沒啥感覺。后面會慢慢體會Django的強大。
另外建議新手不要復制粘貼代碼。科學表明,緩慢的敲入字符有助于提高編程水平。
代碼分解這部分內容如果不能理解也沒關系,先跳過,待水平提高再回過頭來閱讀。
導入(Import)Django框架基于python語言,而在python中用import或者from...import來導入模塊。
模塊其實就一些函數和類的集合文件,它能實現一些相應的功能。當我們需要使用這些功能的時候,直接把相應的模塊導入到我們的程序中就可以使用了。
import用于導入整個功能模塊。但實際使用時往往只需要用模塊中的某一個功能,為此導入整個模塊有點大材小用,因此可以用from a import b表示從模塊a中導入b給我用就可以了。
類(Class)Python作為面向對象編程語言,最重要的概念就是類(Class)和實例(Instance)。
類是抽象的模板,而實例是根據這個類創建出來的一個個具體的“對象”。每個對象都擁有相同的方法,但各自的數據可能不同。而這些方法被打包封裝在一起,就組成了類。
比如說我們剛寫的這個ArticlePost類,作用就是就為博客文章的內容提供了一個模板。每當有一篇新文章生成的時候,都要比對ArticlePost類來創建author、title、body...等等數據;雖然每篇文章的具體內容可能不一樣,但是必須都遵循相同的規則。
在Django中,數據由模型來處理,而模型的載體就是類(Class)。
字段(Field)字段(field)表示數據庫表的一個抽象類,Django使用字段類創建數據庫表,并將Python類型映射到數據庫。
在模型中,字段被實例化為類屬性并表示特定的表,同時具有將字段值映射到數據庫的屬性及方法。
比方說ArticlePost類中有一個title的屬性,這個屬性中保存著Charfield類型的數據:即一個較短的字符串。
ForeignKey外鍵ForeignKey是用來解決“一對多”問題的,用于關聯查詢。
什么叫“一對多”?
在我們的ArticlePost模型中,一篇文章只能有一個作者,而一個作者可以有很多篇文章,這就是“一對多”關系。
又比如一個班級的同學中,每個同學只能有一種性別,而每種性別可以對應很多的同學,這也是“一對多”。
因此,通過ForeignKey外鍵,將User和ArticlePost關聯到了一起,最終就是將博客文章的作者和網站的用戶關聯在一起了。
既然有“一對多”,當然也有“一對一”(OneToOneField )、“多對多”(ManyToManyField)。目前用不到這些外鍵,后面再回頭來對比其差別。
注意這里有個小坑,Django2.0 之前的版本on_delete參數可以不填;Django2.0以后on_delete是必填項,不寫會報錯。
內部類(Meta)內部類class Meta用來使用類提供的模型元數據。模型元數據是“任何不是字段的東西”,例如排序選項ordering、數據庫表名db_table、單數和復數名稱verbose_name和 verbose_name_plural。要不要寫內部類是完全可選的,當然有了它可以幫助理解并規范類的行為。
在class ArticlePost中我們使用的元數據ordering = ("-created",),表明了每當我需要取出文章列表,作為博客首頁時,按照-created(即文章創建時間,負號標識倒序)來排列,保證了最新文章永遠在最頂部位置。
數據遷移(Migrations)編寫好了Model后,接下來就需要進行數據遷移。
遷移是Django對模型所做的更改傳遞到數據庫中的方式。因此每當對數據庫進行了更改(添加、修改、刪除等)操作,都需要進行數據遷移。
Django 的遷移代碼是由你的模型文件自動生成的,它本質上只是個歷史記錄,Django 可以用它來進行數據庫的滾動更新,通過這種方式使其能夠和當前的模型匹配。
在虛擬環境中進入my_blog文件夾(還沒熟悉venv的再溫習: 在Windows中搭建Django的開發環境),輸入python manage.py makemigrations,對模型的更改創建新的遷移表:
(env) e:django_projectmy_blog>python manage.py makemigrations Migrations for "article": articlemigrations