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_project\my_blog>python manage.py makemigrations
Migrations for 'article':
article\migrations\0001_initial.py
- Create model ArticlePost
(env) e:\django_project\my_blog>
通過運行 makemigrations
命令,Django 會檢測你對模型文件的修改,並且把修改的部分儲存爲一次遷移。
然後輸入python manage.py migrate
,應用遷移到數據庫中:
(env) e:\django_project\my_blog>python manage.py migrate
Operations to perform:
Apply all migrations: admin, article, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
...
Applying sessions.0001_initial... OK
(env) e:\django_project\my_blog>
migrate
命令選中所有還沒有執行過的遷移並應用在數據庫上,也就是將模型的更改同步到數據庫結構上。遷移是非常強大的功能,它能讓你在開發過程中持續的改變數據庫結構而不需要重新刪除和創建表。它專注於使數據庫平滑升級而不會丟失數據。
有點拗口,如果沒懂也沒關係,總之在遷移之後,對Model的編寫就算完成了。
總結
本章初步瞭解了Django的MTV模式,編寫了博客文章的Model模型ArticlePost
,並將其遷移到了數據庫中。
下一步就向View進軍,學習如何調取模型中的數據。
-
有疑問請在杜賽的個人網站留言,我會盡快回復。
-
或Email私信我:[email protected]
-
項目完整代碼:Django_blog_tutorial
轉載請告知作者並註明出處。