摘要:而對于標簽來說,一篇文章可以有多個標簽,同一個標簽下也可能有多篇文章,所以我們使用,表明這是多對多的關聯關系。理解多對一和多對多兩種關聯關系我們分別使用了兩種關聯數據庫表的形式和。表明一種一對多的關聯關系。
設計博客的數據庫表結構
博客最主要的功能就是展示我們寫的文章,它需要從某個地方獲取博客文章數據才能把文章展示出來,通常來說這個地方就是數據庫。我們把寫好的文章永久地保存在數據庫里,當用戶訪問我們的博客時,Django 就去數據庫里把這些數據取出來展現給用戶。
博客的文章應該含有標題、正文、作者、發表時間等數據。一個更加現代化的博客文章還希望它有分類、標簽、評論等。為了更好地存儲這些數據,我們需要合理地組織數據庫的表結構。
我們的博客初級版本主要包含博客文章,文章會有分類以及標簽。一篇文章只能有一個分類,但可以打上很多標簽。
數據庫存儲的數據其實就是表格的形式,例如存儲博客文章的數據庫表長這個樣子:
文章 id | 標題 | 正文 | 發表時間 | 分類 | 標簽 |
---|---|---|---|---|---|
1 | title 1 | text 1 | 2016-12-23 | Django | Django 學習 |
2 | title 2 | text 2 | 2016-12-24 | Django | Django 學習 |
3 | title 3 | text 3 | 2016-12-26 | Python | Python 學習 |
其中文章 ID 是一個數字,唯一對應著一篇文章。當然還可以有更多的列以存儲更多相關數據,這只是一個最基本的示例。
數據庫表設計成這樣其實已經可以了,但是稍微分析一下我們就會發現一個問題,這 3 篇文章的分類和標簽都是相同的,這會產生很多重復數據,當數據量很大時就浪費了存儲空間。
不同的文章可能它們對應的分類或者標簽是相同的,所以我們把分類和標簽提取出來,做成多帶帶的數據庫表,再把文章和分類、標簽關聯起來。下面分別是分類和標簽的數據庫表:
分類 id | 分類名 |
---|---|
1 | Django |
2 | Python |
標簽 id | 標簽名 |
---|---|
1 | Django 學習 |
2 | Python 學習 |
以上是自然語言描述的表格,數據庫也和編程語言一樣,有它自己的一套規定的語法來生成上述的表結構,這樣我們才能把數據存進去。一般來說這時候我們應該先去學習數據庫創建表格的語法,再回來寫我們的 Django 博客代碼了。但是 Django 告訴我們不用這么麻煩,它已經幫我們做了一些事情。Django 把那一套數據庫的語法轉換成了 Python 的語法形式,我們只要寫 Python 代碼就可以了,Django 會把 Python 代碼翻譯成對應的數據庫操作語言。用更加專業一點的說法,就是 Django 為我們提供了一套 ORM(Object Relational Mapping)系統。
例如我們的分類數據庫表,Django 只要求我們這樣寫:
blog/models.py from django.db import models class Category(models.Model): name = models.CharField(max_length=100)
Category 就是一個標準的 Python 類,它繼承了 models.Model 類,類名為 Category 。Category 類有一個屬性 name,它是 models.CharField 的一個實例。
這樣,Django 就可以把這個類翻譯成數據庫的操作語言,在數據庫里創建一個名為 category 的表格,這個表格的一個列名為 name。還有一個列 id,Django 則會自動創建。可以看出從 Python 代碼翻譯成數據庫語言時其規則就是一個 Python 類對應一個數據庫表格,類名即表名,類的屬性對應著表格的列,屬性名即列名。
我們需要 3 個表格:文章(Post)、分類(Category)以及標簽(Tag),下面就來分別編寫它們對應的 Python 類。模型的代碼通常寫在相關應用的 models.py 文件里。已經在代碼中做了詳細的注釋,說明每一句代碼的含義。但如果你在移動端下閱讀不便的話,也可以跳到代碼后面看正文的里的講解。
注意:代碼中含有中文注釋,如果你直接 copy 代碼到你的文本編輯器且使用了 Python 2 開發環境的話,會得到一個編碼錯誤。因此請在文件最開始處加入編碼聲明:# coding: utf-8。
blog/models.py from django.db import models from django.contrib.auth.models import User class Category(models.Model): """ Django 要求模型必須繼承 models.Model 類。 Category 只需要一個簡單的分類名 name 就可以了。 CharField 指定了分類名 name 的數據類型,CharField 是字符型, CharField 的 max_length 參數指定其最大長度,超過這個長度的分類名就不能被存入數據庫。 當然 Django 還為我們提供了多種其它的數據類型,如日期時間類型 DateTimeField、整數類型 IntegerField 等等。 Django 內置的全部類型可查看文檔: https://docs.djangoproject.com/en/1.10/ref/models/fields/#field-types """ name = models.CharField(max_length=100) class Tag(models.Model): """ 標簽 Tag 也比較簡單,和 Category 一樣。 再次強調一定要繼承 models.Model 類! """ name = models.CharField(max_length=100) class Post(models.Model): """ 文章的數據庫表稍微復雜一點,主要是涉及的字段更多。 """ # 文章標題 title = models.CharField(max_length=70) # 文章正文,我們使用了 TextField。 # 存儲比較短的字符串可以使用 CharField,但對于文章的正文來說可能會是一大段文本,因此使用 TextField 來存儲大段文本。 body = models.TextField() # 這兩個列分別表示文章的創建時間和最后一次修改時間,存儲時間的字段用 DateTimeField 類型。 created_time = models.DateTimeField() modified_time = models.DateTimeField() # 文章摘要,可以沒有文章摘要,但默認情況下 CharField 要求我們必須存入數據,否則就會報錯。 # 指定 CharField 的 blank=True 參數值后就可以允許空值了。 excerpt = models.CharField(max_length=200, blank=True) # 這是分類與標簽,分類與標簽的模型我們已經定義在上面。 # 我們在這里把文章對應的數據庫表和分類、標簽對應的數據庫表關聯了起來,但是關聯形式稍微有點不同。 # 我們規定一篇文章只能對應一個分類,但是一個分類下可以有多篇文章,所以我們使用的是 ForeignKey,即一對多的關聯關系。 # 而對于標簽來說,一篇文章可以有多個標簽,同一個標簽下也可能有多篇文章,所以我們使用 ManyToManyField,表明這是多對多的關聯關系。 # 同時我們規定文章可以沒有標簽,因此為標簽 tags 指定了 blank=True。 # 如果你對 ForeignKey、ManyToManyField 不了解,請看教程中的解釋,亦可參考官方文檔: # https://docs.djangoproject.com/en/1.10/topics/db/models/#relationships category = models.ForeignKey(Category) tags = models.ManyToManyField(Tag, blank=True) # 文章作者,這里 User 是從 django.contrib.auth.models 導入的。 # django.contrib.auth 是 Django 內置的應用,專門用于處理網站用戶的注冊、登錄等流程,User 是 Django 為我們已經寫好的用戶模型。 # 這里我們通過 ForeignKey 把文章和 User 關聯了起來。 # 因為我們規定一篇文章只能有一個作者,而一個作者可能會寫多篇文章,因此這是一對多的關聯關系,和 Category 類似。 author = models.ForeignKey(User)博客模型代碼代碼詳解
首先是 Category 和 Tag 類,它們均繼承自 model.Model 類,這是 Django 規定的。Category 和 Tag 類均有一個 name 屬性,用來存儲它們的名稱。由于分類名和標簽名一般都是用字符串表示,因此我們使用了 CharField 來指定 name 的數據類型,同時 max_length 參數則指定 name 允許的最大長度,超過該長度的字符串將不允許存入數據庫。除了 CharField ,Django 還為我們提供了更多內置的數據類型,比如時間類型 DateTimeField、整數類型 IntegerField 等等。
在本教程中我們會教你這些類型的使用方法,但以后你開發自己的項目時,你就需要通過閱讀Django 官方文檔 關于字段類型的介紹 來了解有哪些數據類型可以使用以及如何使用它們。
Post 類也一樣,必須繼承自 model.Model 類。文章的數據庫表稍微復雜一點,主要是列更多,我們指定了這些列:
title。這是文章的標題,數據類型是 CharField,允許的最大長度 max_length = 70。
body。文章正文,我們使用了 TextField。比較短的字符串存儲可以使用 CharField,但對于文章的正文來說可能會是一大段文本,因此使用 TextField 來存儲大段文本。
created_time、modified_time。這兩個列分別表示文章的創建時間和最后一次修改時間,存儲時間的列用 DateTimeField 數據類型。
excerpt。文章摘要,可以沒有文章摘要,但默認情況下 CharField 要求我們必須存入數據,否則就會報錯。指定 CharField 的 blank=True 參數值后就可以允許空值了。
category 和 tags。這是分類與標簽,分類與標簽的模型我們已經定義在上面。我們把文章對應的數據庫表和分類、標簽對應的數據庫表關聯了起來,但是關聯形式稍微有點不同。我們規定一篇文章只能對應一個分類,但是一個分類下可以有多篇文章,所以我們使用的是 ForeignKey,即一對多的關聯關系。而對于標簽來說,一篇文章可以有多個標簽,同一個標簽下也可能有多篇文章,所以我們使用 ManyToManyField,表明這是多對多的關聯關系。同時我們規定文章可以沒有標簽,因此為標簽 tags 指定了 blank=True。
author。文章作者,這里 User 是從 django.contrib.auth.models 導入的。django.contrib.auth 是 Django 內置的應用,專門用于處理網站用戶的注冊、登錄等流程。其中 User 是 Django 為我們已經寫好的用戶模型,和我們自己編寫的 Category 等類是一樣的。這里我們通過 ForeignKey 把文章和 User關聯了起來,因為我們規定一篇文章只能有一個作者,而一個作者可能會寫多篇文章,因此這是一對多的關聯關系,和 Category 類似。
理解多對一和多對多兩種關聯關系我們分別使用了兩種關聯數據庫表的形式:ForeignKey 和 ManyToManyField。
ForeignKeyForeignKey 表明一種一對多的關聯關系。比如這里我們的文章和分類的關系,一篇文章只能對應一個分類,而一個分類下可以有多篇文章。反應到數據庫表格中,它們的實際存儲情況是這樣的:
文章 ID | 標題 | 正文 | 分類 ID |
---|---|---|---|
1 | title 1 | body 1 | 1 |
2 | title 2 | body 2 | 1 |
3 | title 3 | body 3 | 1 |
4 | title 4 | body 4 | 2 |
分類 ID | 分類名 | |
---|---|---|
1 | Django | |
2 | Python |
可以看到文章和分類實際上是通過文章數據庫表中 分類 ID 這一列關聯的。當要查詢文章屬于哪一個分類時,只需要查看其對應的分類 ID 是多少,然后根據這個分類 ID 就可以從分類數據庫表中找到該分類的數據。例如這里文章 1、2、3 對應的分類 ID 均為 1,而分類 ID 為 1 的分類名為 Django,所以文章 1、2、3 屬于分類 Django。同理文章 4 屬于分類 Python。
反之,要查詢某個分類下有哪些文章,只需要查看對應該分類 ID 的文章有哪些即可。例如這里 Django 的分類 ID 為 1,而對應分類 ID 為 1 的文章有文章 1、2、3,所以分類 Django 下有 3 篇文章。
希望這個例子能幫助你加深對多對一關系,以及它們在數據庫中是如何被關聯的理解,更多的例子請看文末給出的 Django 官方參考資料。
ManyToManyFieldManyToManyField 表明一種多對多的關聯關系,比如這里的文章和標簽,一篇文章可以有多個標簽,而一個標簽下也可以有多篇文章。反應到數據庫表格中,它們的實際存儲情況是這樣的:
文章 ID | 標題 | 正文 |
---|---|---|
1 | title 1 | body 1 |
2 | title 2 | body 2 |
3 | title 3 | body 3 |
4 | title 4 | body 4 |
標簽 ID | 標簽名 |
---|---|
1 | Django 學習 |
2 | Python 學習 |
文章 ID | 標簽 ID |
---|---|
1 | 1 |
1 | 2 |
2 | 1 |
3 | 2 |
多對多的關系無法再像一對多的關系中的例子一樣在文章數據庫表加一列 分類 ID 來關聯了,因此需要額外建一張表來記錄文章和標簽之間的關聯。例如文章 ID 為 1 的文章,既對應著 標簽 ID 為 1 的標簽,也對應著 標簽 ID 為 2 的標簽,即文章 1 既屬于標簽 1:Django 學習,也屬于標簽 2:Python 學習。
反之,標簽 ID 為 1 的標簽,既對應著 文章 ID 為 1 的文章,也對應著 文章 ID 為 2 的文章,即標簽 1:Django 學習下有兩篇文章。
希望這個例子能幫助你加深對多對多關系,以及它們在數據庫中是如何被關聯的理解,更多的例子請看文末給出的 Django 官方參考資料。
假如你對多對一關系和多對多關系還存在一些困惑,強烈建議閱讀官方文檔對這兩種關系的說明以及更多官方的例子以加深理解:
Django ForeignKey 簡介
Django ForeignKey 詳細示例
Django ManyToManyField 簡介
Django ManyToManyField 詳細示例
總結本章節的代碼位于:Step3: blog models。
如果遇到問題,請通過下面的方式尋求幫助。
在 創建 Django 博客的數據庫模型 - 追夢人物的博客 的評論區留言。
將問題的詳細描述通過郵件發送到 djangostudyteam@163.com,一般會在 24 小時內回復。
更多Django 教程,請訪問 追夢人物的博客。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44402.html
摘要:注意每篇文章必須有一個分類,在添加文章時你可以選擇已有分類。在在后臺發布文章追夢人物的博客的評論區留言。將問題的詳細描述通過郵件發送到,一般會在小時內回復。 在此之前我們完成了 Django 博客首頁視圖的編寫,我們希望首頁展示發布的博客文章列表,但是它卻抱怨:暫時還沒有發布的文章!如它所言,我們確實還沒有發布任何文章,本節我們將使用 Django 自帶的 Admin 后臺來發布我們的...
摘要:創建了數據庫模型就要遷移數據庫,遷移數據庫的命令也在前面講過。如果表單對應有一個數據庫模型例如這里的評論表單對應著評論模型,那么使用類會簡單很多,這是為我們提供的方便。表明這個表單對應的數據庫模型是類。 創建評論應用 相對來說,評論其實是另外一個比較獨立的功能。Django 提倡,如果功能相對比較獨立的話,最好是創建一個應用,把相應的功能代碼寫到這個應用里。我們的第一個應用叫 blog...
摘要:激活虛擬環境,切換到文件所在的目錄下,分別運行和命令注意如果代碼中含有中文注釋,且你使用的是開發環境的話,會得到一個編碼錯誤。因此請在含有中文注釋的文件最開始處加入編碼聲明。在讓完成翻譯遷移數據庫追夢人物的博客的評論區留言。 我們已經編寫了博客數據庫模型的代碼,但那還只是 Python 代碼而已,Django 還沒有把它翻譯成數據庫語言,因此實際上這些數據庫表還沒有真正的在數據庫中創建...
摘要:所以,讓我們再接再厲,進入到博客開發進階教程,學習更多的開發技巧,為博客提供更多的功能吧總結本章節的代碼位于。在已知小問題修正追夢人物的博客的評論區留言。將問題的詳細描述通過郵件發送到,一般會在小時內回復。更多教程,請訪問追夢人物的博客。 在模型中指定排序 為了讓文章(Post)按發布時間逆序排列,即最新發表的文章排在文章列表的最前面,我們對返回的文章列表進行了排序,即各個視圖函數中都...
如何精確地記錄一篇文章的閱讀量是一個比較復雜的問題,不過對于我們的博客來說,沒有必要記錄的那么精確。因此我們使用一種簡單但有效的方式來記錄博客文章的閱讀量:文章每被瀏覽一次,則其閱讀量 +1,即所謂的文章頁面 PV(Page View)數。雖然簡單粗暴,但卻高效實用。 增加新字段 為了記錄文章的瀏覽量,需要在文章的數據庫表中新增一個用于存儲閱讀量的字段。因此給博客文章的模型新增一個 views 字...
閱讀 1428·2021-11-22 15:24
閱讀 2519·2021-10-11 11:06
閱讀 2323·2021-10-09 09:45
閱讀 2525·2021-09-09 09:33
閱讀 634·2019-08-30 15:53
閱讀 1439·2019-08-30 12:48
閱讀 656·2019-08-29 13:47
閱讀 500·2019-08-26 18:27