教程目錄
1.1 CoolBlog開發(fā)筆記第1課:項(xiàng)目分析
1.2 CoolBlog開發(fā)筆記第2課:搭建開發(fā)環(huán)境
1.3 CoolBlog開發(fā)筆記第3課:創(chuàng)建Django應(yīng)用
前言
我新書《Python爬蟲開發(fā)與項(xiàng)目實(shí)戰(zhàn)》出版了。 這本書包括基礎(chǔ)篇,中級(jí)篇和深入篇三個(gè)部分,不僅適合零基礎(chǔ)的朋友入門,也適合有一定基礎(chǔ)的爬蟲愛(ài)好者進(jìn)階,如果你不會(huì)分布式爬蟲,不會(huì)千萬(wàn)級(jí)數(shù)據(jù)的去重,不會(huì)怎么突破反爬蟲,不會(huì)分析js的加密,這本書會(huì)給你驚喜。如果大家對(duì)這本書感興趣的話,可以看一下 試讀樣章。廢話少說(shuō),開始講正題。從上一節(jié)我們知道home應(yīng)用需要涉及文章,分類和標(biāo)簽三個(gè)部分,其實(shí)這就是個(gè)人博客系統(tǒng)最核心的功能:發(fā)表文章。下面我們分析一下數(shù)據(jù)庫(kù)該如何設(shè)計(jì)?
1.4.1數(shù)據(jù)庫(kù)設(shè)計(jì)
1.先從分類說(shuō)起,從下圖中我們知道一個(gè)博客中對(duì)文章有很多分類,因此分類需要作為單獨(dú)的數(shù)據(jù)表,里面需要存儲(chǔ)分類的id和名稱。
2.標(biāo)簽和分類類似,如下所示,博客有很多標(biāo)簽標(biāo)記文章的主題,標(biāo)簽需要作為單獨(dú)的數(shù)據(jù)表,里面需要存儲(chǔ)標(biāo)簽的id和名稱。
3.文章的存儲(chǔ)是相對(duì)復(fù)雜的,從項(xiàng)目分析的圖1.4可以看到,文章數(shù)據(jù)表需要存儲(chǔ)文章的標(biāo)題,內(nèi)容,創(chuàng)建時(shí)間,修改時(shí)間,摘要,分類,標(biāo)簽,作者,瀏覽量和評(píng)論數(shù),要存儲(chǔ)的數(shù)據(jù)有幾個(gè)需要注意:分類,標(biāo)簽和評(píng)論數(shù)。
首先在設(shè)計(jì)數(shù)據(jù)表時(shí)不考慮評(píng)論數(shù),因?yàn)樵u(píng)論我們已經(jīng)作為一個(gè)獨(dú)立的應(yīng)用,而且這和評(píng)論數(shù)據(jù)表與文章數(shù)據(jù)表的關(guān)系有關(guān)聯(lián),之后在講評(píng)論功能時(shí)會(huì)說(shuō)明。
文章數(shù)據(jù)表中有分類和標(biāo)簽的字段,如果大家有設(shè)計(jì)數(shù)據(jù)庫(kù)的經(jīng)歷,此時(shí)應(yīng)該很敏感,這時(shí)候需要考慮文章數(shù)據(jù)表與分類數(shù)據(jù)表,標(biāo)簽數(shù)據(jù)表的關(guān)系。
一個(gè)分類下可以有很多文章,而一篇文章只能有一個(gè)分類,這是一對(duì)多的關(guān)系。
一個(gè)標(biāo)簽下可以有很多文章,同樣一篇文章可以有很多標(biāo)簽,這是多對(duì)多的關(guān)系。
通過(guò)上面的分析,我們使用Mysql Workbench設(shè)計(jì)如下三個(gè)數(shù)據(jù)表:Category表,Tag表和Article表,并描述了三個(gè)表之間的關(guān)系。
Category表通過(guò)外鍵與Acticle表相連,而Tag表與Article之間很特殊。大家會(huì)發(fā)現(xiàn)很奇怪,為什么設(shè)計(jì)了三個(gè)表,可是上圖中卻多出了一個(gè)Article_has_Tag表。這是為什么呢?其實(shí)這在數(shù)據(jù)庫(kù)設(shè)計(jì)中很常見,描述兩個(gè)表多對(duì)多的關(guān)系時(shí),會(huì)生成一個(gè)中間表,將多對(duì)多的關(guān)系轉(zhuǎn)化為兩個(gè)表和中間表一對(duì)多的關(guān)系,這樣可以使用外鍵將表聯(lián)系起來(lái)。不過(guò)在代碼實(shí)現(xiàn)時(shí),是不用體現(xiàn)類似Acticle_has_Tag中間表的,Django會(huì)幫我們完成,咱們繼續(xù)往下看。
1.4.2編寫數(shù)據(jù)庫(kù)模型
打開home應(yīng)用下的models.py文件,這個(gè)文件是專門用來(lái)描述應(yīng)用的數(shù)據(jù)庫(kù)模型。
由于通過(guò)ORM的方式,因此在models中一個(gè)類即是一個(gè)數(shù)據(jù)表,一個(gè)屬性對(duì)應(yīng)著數(shù)據(jù)表中的字段。下面先把Category表列一下:
1 2 3 | class Category(models.Model): #分類名稱 name = models.CharField(max_length = 50 ,verbose_name = "分類名稱" ) |
在上面的代碼中,定義一個(gè)數(shù)據(jù)庫(kù)模型,需要繼承models.Model類,name是類中的一個(gè)屬性,它是models.CharField的一個(gè)實(shí)例,對(duì)應(yīng)著Category數(shù)據(jù)表中name字段。在1.4.1節(jié)中,設(shè)計(jì)的Category數(shù)據(jù)表中還有id字段,由于Django會(huì)默認(rèn)創(chuàng)建id字段作為主鍵,這里我們不用再聲明。models.CharField類的的初始化參數(shù)max_length代表著這存儲(chǔ)數(shù)據(jù)的最大長(zhǎng)度,verbose_name用來(lái)對(duì)name屬性進(jìn)行描述,在界面顯示時(shí)有用。CharField主要用來(lái)存儲(chǔ)短文本,可以看做是數(shù)據(jù)庫(kù)中的varchar(50)。同樣的道理,Tag類的內(nèi)容如下:
1 2 3 | class Tag(models.Model): # 名稱 name = models.CharField(max_length = 50 ,verbose_name = "標(biāo)簽名稱" ) |
下面定義復(fù)雜的Acticle表,一定要看注釋。內(nèi)容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Article(models.Model): # 文章標(biāo)題 title = models.CharField(max_length = 70 ,verbose_name = "文章標(biāo)題" ) #文章內(nèi)容 body = models.TextField(verbose_name = "文章內(nèi)容" ,default = '') #創(chuàng)建時(shí)間 created_time = models.DateTimeField(verbose_name = "創(chuàng)建時(shí)間" ) # 修改時(shí)間 modified_time = models.DateTimeField(verbose_name = "修改時(shí)間" ) # 摘要 excerpt = models.CharField(max_length = 200 , blank = True ,verbose_name = "摘要" ) # 分類 category = models.ForeignKey(Category,verbose_name = "分類" ) # 標(biāo)簽 tags = models.ManyToManyField(Tag, blank = True ,verbose_name = u "標(biāo)簽" ) # 作者 author = models.ForeignKey(User,verbose_name = "作者" ) #瀏覽量 views = models.PositiveIntegerField(defalut = 0verbose_name = "瀏覽量" ) |
在上面的代碼中主要有幾點(diǎn)需要說(shuō)明:
body使用TextField來(lái)描述,它和CharField不同,用來(lái)存儲(chǔ)大段的文本,default參數(shù)是用來(lái)設(shè)置字段的默認(rèn)值,body默認(rèn)設(shè)置為空。
created_time和modified_time使用DateTimeField來(lái)表述,用來(lái)存儲(chǔ)日期,大家可以想想數(shù)據(jù)庫(kù)中用什么類型存儲(chǔ)時(shí)間呢。
excerpt用來(lái)存儲(chǔ)文章的摘要,blank=True參數(shù)的意思是用來(lái)說(shuō)明此字段可以為空值。
category用來(lái)表示分類,通過(guò)傳入Category類實(shí)例化ForeignKey,來(lái)描述一對(duì)多的關(guān)系。
tags表示文章標(biāo)簽,通過(guò)傳入Tag類實(shí)例化ManyToManyField,來(lái)表述多對(duì)多的關(guān)系,同時(shí)傳入blank=True來(lái)設(shè)置可以為空。
author表示文章作者,大家會(huì)發(fā)現(xiàn)我們使用了外鍵,這是因?yàn)閁ser是Django內(nèi)置的數(shù)據(jù)模型,從django.contrib.auth.models中導(dǎo)入的,專門用來(lái)負(fù)責(zé)用戶信息的處理,本質(zhì)上User就是一個(gè)數(shù)據(jù)表。一個(gè)作者可以擁有很多文章,而一篇文章只能有一個(gè)作者,是一對(duì)多的關(guān)系,因此使用外鍵和User數(shù)據(jù)模型建立聯(lián)系。
Views表示瀏覽量,通過(guò)實(shí)例化models.PositiveIntegerField來(lái)實(shí)現(xiàn),PositiveIntegerField該類型只允許正整數(shù)和0,也就是說(shuō)Views>=0。
經(jīng)過(guò)以上的分析,數(shù)據(jù)模型基本上建立起來(lái)了,不過(guò)這還沒(méi)有結(jié)束,因?yàn)檫€沒(méi)有完成模型到真實(shí)數(shù)據(jù)庫(kù)的遷移。接下來(lái)要做的是配置數(shù)據(jù)庫(kù),完成代碼到數(shù)據(jù)庫(kù)的“翻譯”。
1.4.3數(shù)據(jù)庫(kù)模型遷移
打開CoolBlog工程CoolBlog目錄下的settings.py文件,其中Django已經(jīng)默認(rèn)配置好了sqlite3數(shù)據(jù)庫(kù)。
DATABASES變量用來(lái)配置數(shù)據(jù)庫(kù),ENGINE代表使用數(shù)據(jù)庫(kù)引擎,NAME對(duì)于sqlite3這種單文件數(shù)據(jù)庫(kù)來(lái)說(shuō),代表著它的存儲(chǔ)路徑。但是這次我們不用默認(rèn)的sqlite3數(shù)據(jù)庫(kù),在稍微大型的項(xiàng)目中,Mysql才是標(biāo)配。首先使用Navicat for MySQL打開MySQL,新建一個(gè)coolblog數(shù)據(jù)庫(kù)。
新建成功后,咱們接著在settings.py文件中配置MySQL。修改如下:
1 2 3 4 5 6 7 8 9 10 | DATABASES = { 'default' : { 'ENGINE' : 'django.db.backends.mysql' , 'NAME' : 'coolblog' , #數(shù)據(jù)庫(kù)名稱 'USER' : 'root' , #用戶名 'PASSWORD' :'', #密碼為空 'HOST' : '127.0.0.1' , #主機(jī) 'PORT' : '3308' #端口 } } |
大家根據(jù)自己的MySQL進(jìn)行配置。如果不想用MySQL,可以依然保持原樣。配置完成后,開始進(jìn)行通過(guò)Django提供的命令進(jìn)行數(shù)據(jù)庫(kù)遷移。激活虛擬環(huán)境,并切換到CoolBlog項(xiàng)目下,首先運(yùn)行 python manage.py makemigrations命令會(huì)報(bào)出如下的錯(cuò)誤,大致的意思是缺少M(fèi)ySQLdb模塊。
由于我們使用MySQL作為數(shù)據(jù)庫(kù)遷移,需要安裝python版本MySQL引擎,Django默認(rèn)使用MySQLdb。接下來(lái)理所當(dāng)然是安裝MySQLdb,但是作為有安裝經(jīng)驗(yàn)的人,很負(fù)責(zé)任地告訴大家MySQLdb在Windows平臺(tái)下安裝很不方便,尤其是有多個(gè)Python版本的時(shí)候,坑很多,因此我們這里不使用MySQLdb,我們使用另外一個(gè)更加友好流行的引擎:PyMySQL。我們?cè)谔摂M環(huán)境中運(yùn)行:pip3 install pymysql。安裝成功后,我們需要在與settings.py同級(jí)目錄的__init__文件中加入以下代碼:
1 2 | import pymysql pymysql.install_as_MySQLdb() |
這樣就將Django默認(rèn)的MySQLdb進(jìn)行了替換。下面接著運(yùn)行python manage.py makemigrations和python manage.py migrate命令。執(zhí)行效果如下圖所示:
這樣就完成了數(shù)據(jù)庫(kù)模型的遷移,那咱們看看數(shù)據(jù)庫(kù)有沒(méi)有新建的表?下圖所示,Django已經(jīng)幫助我們完成了數(shù)據(jù)庫(kù)的遷移,里面是不是還有之前說(shuō)的中間表!
下面給大家講解一下上面兩條數(shù)據(jù)模型遷移命令到底干了些什么事情?
makemigrations命令:是用來(lái)記錄應(yīng)用數(shù)據(jù)模型的改動(dòng),這些改動(dòng)會(huì)記錄到應(yīng)用所在目錄的migrations文件夾下,大家會(huì)看到里面產(chǎn)生了一些python文件,比如初次生成的0001_initial.py文件。
migrate命令才是真正意義上將應(yīng)用數(shù)據(jù)模型映射到數(shù)據(jù)庫(kù)中,Django通過(guò)檢測(cè)migrations文件夾下的文件,就可以知道我們對(duì)數(shù)據(jù)模型做了哪些修改,然后Django將這些改動(dòng)翻譯成SQL語(yǔ)句,并作用于數(shù)據(jù)庫(kù)。比如home應(yīng)用,migrate命令其實(shí)是在檢查剛才makemigrations命令生成的0001_initial.py腳本,將這些改動(dòng)應(yīng)用到數(shù)據(jù)庫(kù)中。
那Django將這些模型的改動(dòng)翻譯成什么樣的SQL語(yǔ)句呢?我么可以通過(guò)sqlmigrate 命令進(jìn)行查看。在命令行中執(zhí)行:python manage.py sqlmigrate home 0001。如下圖所示。
大家有沒(méi)有發(fā)現(xiàn),除了home應(yīng)用的數(shù)據(jù)庫(kù)模型進(jìn)行了遷移,還有很多數(shù)據(jù)的改動(dòng),其實(shí)這是為Django內(nèi)置的應(yīng)用進(jìn)行數(shù)據(jù)模型的遷移。大家可以和settings.py中的INSTALLED_APPS變量聯(lián)系起來(lái)看。
本節(jié)課程結(jié)束了,下一節(jié)咱們接著講,要涉及到請(qǐng)求與響應(yīng)方面的內(nèi)容了。
最后
我新書《Python爬蟲開發(fā)與項(xiàng)目實(shí)戰(zhàn)》出版了。 這本書包括基礎(chǔ)篇,中級(jí)篇和深入篇三個(gè)部分,不僅適合零基礎(chǔ)的朋友入門,也適合有一定基礎(chǔ)的爬蟲愛(ài)好者進(jìn)階,如果你不會(huì)分布式爬蟲,不會(huì)千萬(wàn)級(jí)數(shù)據(jù)的去重,不會(huì)怎么突破反爬蟲,不會(huì)分析js的加密,這本書會(huì)給你驚喜。如果大家對(duì)這本書感興趣的話,可以看一下 試讀樣章。
http://www.cnblogs.com/qiyeboy/p/7079462.html