Django搭建個人部落格:編寫部落格文章的Model模型

杜賽_dusai發表於2018-09-29

Django 框架主要關注的是模型(Model)、模板(Template)和檢視(Views),稱為MTV模式。

它們各自的職責如下:

層次 職責
模型(Model),即資料存取層 處理與資料相關的所有事務: 如何存取、如何驗證有效性、包含哪些行為以及資料之間的關係等。
模板(Template),即業務邏輯層 處理與表現相關的決定: 如何在頁面或其他型別文件中進行顯示。
檢視(View),即表現層 存取模型及調取恰當模板的相關邏輯。模型與模板的橋樑。

簡單來說就是Model存取資料,View決定需要調取哪些資料,而Template則負責將調取出的資料以合理的方式展現出來。

在 Django 裡寫一個資料庫驅動的 Web 應用的第一步是定義模型Model,也就是資料庫結構設計和附加的其它後設資料。

模型包含了儲存的資料所必要的欄位和行為。Django 的目標是你只需要定義資料模型,其它的雜七雜八程式碼你都不用關心,它們會自動從模型生成。

所以讓我們首先搞定Model

編寫 Model

如前面所講,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類來建立authortitlebody...等等資料;雖然每篇文章的具體內容可能不一樣,但是必須都遵循相同的規則。

在Django中,資料由模型來處理,而模型的載體就是類(Class)。

欄位(Field)

欄位(field)表示資料庫表的一個抽象類,Django使用欄位類建立資料庫表,並將Python型別對映到資料庫。

在模型中,欄位被例項化為類屬性並表示特定的表,同時具有將欄位值對映到資料庫的屬性及方法。

比方說ArticlePost類中有一個title的屬性,這個屬性中儲存著Charfield型別的資料:即一個較短的字串。

ForeignKey外來鍵

ForeignKey是用來解決“一對多”問題的,用於關聯查詢。

什麼叫“一對多”?

在我們的ArticlePost模型中,一篇文章只能有一個作者,而一個作者可以有很多篇文章,這就是“一對多”關係

又比如一個班級的同學中,每個同學只能有一種性別,而每種性別可以對應很多的同學,這也是“一對多”。

因此,通過ForeignKey外來鍵,將UserArticlePost關聯到了一起,最終就是將部落格文章的作者和網站的使用者關聯在一起了。

既然有“一對多”,當然也有**“一對一”(OneToOneField)、“多對多”(ManyToManyField)**。目前用不到這些外來鍵,後面再回頭來對比其差別。

注意這裡有個小坑,Django2.0 之前的版本on_delete引數可以不填;Django2.0以後on_delete是必填項,不寫會報錯。

內部類(Meta)

內部類class Meta用來使用類提供的模型後設資料。模型後設資料是**“任何不是欄位的東西”**,例如排序選項ordering、資料庫表名db_table、單數和複數名稱verbose_nameverbose_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進軍,學習如何調取模型中的資料。

轉載請告知作者並註明出處。

相關文章