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