使用python和Django完成部落格資料庫的遷移方法,pythondjango
上一講完成了基本部落格的配置和項目工程的產生。這次開始將部落格一些基本的操作主要是資料庫方面學習。
1.設計部落格資料庫表結構
部落格最主要的功能就是展示我們寫的文章,它需要從某個地方擷取部落格文章資料才能把文章展示出來,通常來說這個地方就是資料庫。我們把寫好的文章永久地儲存在資料庫裡,當使用者訪問我們的部落格時,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.pyfrom django.db import modelsclass Category(models.Model): name = models.CharField(max_length=100)
給出完整的代碼:
from django.db import modelsfrom django.contrib.auth.models import Userfrom django.utils.six import python_2_unicode_compatible# python_2_unicode_compatible 裝飾器用於相容 Python2@python_2_unicode_compatibleclass 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) def __str__(self): return self.name@python_2_unicode_compatibleclass Tag(models.Model): """ 標籤 Tag 也比較簡單,和 Category 一樣。 再次強調一定要繼承 models.Model 類! """ name = models.CharField(max_length=100) def __str__(self): return self.name@python_2_unicode_compatibleclass 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) def __str__(self): return self.title
Category 就是一個標準的 Python 類,它繼承了 models.Model 類,類名為 Category 。Category 類有一個屬性 name,它是 models.CharField 的一個執行個體。
這樣,Django 就可以把這個類翻譯成資料庫的操作語言,在資料庫裡建立一個名為 category 的表格,這個表格的一個列名為 name。還有一個列 id,Django 則會自動建立。可以看出從 Python 代碼翻譯成資料庫語言時其規則就是一個 Python 類對應一個資料庫表格,類名即表名,類的屬性對應著表格的列,屬性名稱即列名。
我們需要 3 個表格:文章(Post)、分類(Category)以及標籤(Tag),下面就來分別編寫它們對應的 Python 類。模型的代碼通常寫在相關應用的 models.py 檔案裡。
二:遷移資料庫
為了讓 Django 完成翻譯,建立好這些資料庫表,我們再一次請出我的工程管理助手 manage.py。啟用虛擬環境,切換到 manage.py 檔案所在的目錄下,分別運行 python manage.py makemigrations 和 python manage.py migrate 命令:
注意:如果代碼中含有中文注釋,且你使用的是 Python 2 開發環境的話,會得到一個編碼錯誤。因此請在含有中文注釋的檔案最開始處加入編碼聲明:# coding: utf-8。
當我們執行了 python manage.py makemigrations 後,Django 在 blog 應用的 migrations\ 目錄下產生了一個 0001_initial.py 檔案,這個檔案是 Django 用來記錄我們對模型做了哪些修改的檔案。目前來說,我們在 models.py 檔案裡建立了 3 個模型類,Django 把這些變化記錄在了 0001_initial.py 裡。
不過此時還只是告訴了 Django 我們做了哪些改變,為了讓 Django 真正地為我們建立資料庫表,接下來又執行了 python manage.py migrate 命令。Django 通過檢測應用中 migrations\ 目錄下的檔案,得知我們對資料庫做了哪些操作,然後它把這些操作翻譯成資料庫操作語言,從而把這些操作作用於真正的資料庫。
你可以看到命令的輸出除了 Applying blog.0001_initial... OK 外,Django 還對其它檔案做了操作。這是因為除了我們自己建立的 blog 應用外,Django 自身還內建了很多應用,這些應用本身也是需要儲存資料的。可以在 settings.py 的 INSTALLED_APP 設定裡看到這些應用,當然我們目前不必關心這些。
blogproject/settings.pyINSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'blog',]
對於瞭解資料庫語言的人,你可以運行下面的命令看看 Django 究竟為我們做了什麼:
python manage.py sqlmigrate blog 0001
你將看到輸出了經 Django 翻譯後的資料庫表建立語句,這有助於你理解 Django ORM 的工作機制。
三:選擇資料庫版本
沒有安裝任何的資料庫軟體,Django 就幫我們遷移了資料庫。這是因為我們使用了 Python 內建的 SQLite3 資料庫。
SQLite3 是一個十分輕巧的資料庫,它僅有一個檔案。你可以看一到項目根目錄下多出了一個 db.sqlite3 的檔案,這就是 SQLite3 資料庫檔案,Django 部落格的資料都會儲存在這個資料庫檔案裡。
Django 在 settings.py 裡為我們做了一些預設的資料庫配置:
blogproject/settings.py## 其它配置選項...DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), }}## 其它配置選項...
可以看到預設的資料庫引擎就是使用的 SQLite3。
當然一些人傾向於使用 MySQL 等大型資料庫,至於 Django 如何配置 MySQL 這裡就不贅述了,你可以自行使用搜尋引擎或者查閱 Django 的官方文檔解決。對於一個小型部落格而言,SQLite3 資料庫足以勝任。
四:用Django方式操作資料庫
資料庫最主要的操作就是往裡面存入資料、從中取出資料、修改已儲存的資料和刪除不再需要的資料。和建立資料庫表一樣,Django 為這些操作提供了一整套方法,從而把我們從資料庫語言中解放出來。我們不用學習如何利用資料庫語言去完成這些操作,只要簡單地調用幾個 Python 函數就可以滿足我們的需求。
存資料
先在命令列中來探索一下這些函數,感受一下如何用 Django 的方式來操作資料庫。在 manage.py 所在目錄下運行 python manage.py shell 命令:
建立一個分類和一個標籤:
首先匯入 3 個之前寫好的模型類,然後執行個體化了一個 Category 類和一個 Tag 類,為他們的屬性 name 賦了值。為了讓 Django 把這些資料儲存進資料庫,調用執行個體的 save 方法即可。
再建立一篇文章試試,但建立文章之前,我們需要先建立一個 User,用於指定文章的作者。建立 User 的命令 Django 已經幫我們寫好了,依然是通過 manage.py 來運行。首先按住 Ctrl + c 退出命令互動欄(一次退不出就連續多按幾次),運行 python manage.py createsuperuser 命令並根據提示建立使用者:
(密碼過於簡單會通不過)
再次運行 python manage.py shell 進入 Python 命令互動欄,開始建立文章:
由於我們重啟了 shell,因此需要重新匯入了 Category、Tag、Post 以及 User。我們還匯入了一個 Django 提供的輔助模組 timezone,這是因為我們需要調用它的 now() 方法為 created_time 和 modified_time 指定時間,容易理解 now 方法返回目前時間。然後我們根據使用者名稱和分類名,通過 get 方法取出了存在資料庫中的 User 和 Category(取資料的方法將在下面介紹)。接著我們為文章指定了 title、body 、created_time、modified_time值,並把它和前面建立的 Category 以及 User 關聯了起來。允許為空白 excerpt、tags 我們就沒有為它們指定值了。
注意:我們這裡使用 get 方法根據 Category 的 name 屬性的值擷取分類的一條記錄。Category.objects.get(name='category test') 的含義是從資料庫中取出 name 的值為 category test 的分類記錄。確保資料庫中只有一條值為 category test 的記錄,否則 get 方法將返回一個 MultipleObjectsReturned 異常。如果你不小心已經存了多條記錄,請刪掉多餘的記錄。如何刪除資料請看下文。
取資料
資料已經存入資料庫了,現在要把它們取出來看看:
objects 是我們的模型管理器,它為我們提供一系列從資料庫中取資料方法,這裡我們使用了 all 方法,表示我們要把對應的資料全部取出來。可以看到 all 方法都返回了資料,這些資料應該是我們之前存進去的,但是顯示的字串有點奇怪,無法看出究竟是不是我們之前存入的資料。為了讓顯示出來的資料更加人性化一點,我們為 3 個模型分別增加一個 __str__ 方法:
from django.db import modelsfrom django.contrib.auth.models import Userfrom django.utils.six import python_2_unicode_compatible# python_2_unicode_compatible 裝飾器用於相容 Python2@python_2_unicode_compatibleclass 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) def __str__(self): return self.name@python_2_unicode_compatibleclass Tag(models.Model): """ 標籤 Tag 也比較簡單,和 Category 一樣。 再次強調一定要繼承 models.Model 類! """ name = models.CharField(max_length=100) def __str__(self): return self.name@python_2_unicode_compatibleclass 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) def __str__(self): return self.title
定義好 __str__ 方法後,解譯器顯示的內容將會是 __str__ 方法返回的內容。這裡 Category 返回分類名 name ,Tag 返回標籤名,而 Post 返回它的 title。
python_2_unicode_compatible 裝飾器用於相容 Python2。如果你使用的 Python3 開發環境,去掉這個裝飾器不會有任何影響。如果你使用的 Python2 開發環境,而又不想使用這個裝飾器,則將 __str__ 方法改為 __unicode__ 方法即可。
先按 Ctrl + c 退出 Shell,再重新運行 python manage.py shell 進入 Shell。
改資料:
首先通過 get 方法根據分類名 name 擷取值為 category test 到分類,修改它的 name 屬性為新的值 category test new,然後調用 save 方法把修改儲存到資料庫,之後可以看到資料庫返回的資料已經是修改後的值了。Tag、Post的修改也一樣。
刪除資料:
先根據標題 title 的值從資料庫中取出 Post,儲存在變數 p 中,然後調用它的delete 方法,最後看到 Post.objects.all() 返回了一個空的 QuerySet(類似於一個列表),表明資料庫中已經沒有 Post,Post 已經被刪除了。
這就是 Django 對資料庫增、刪、改、查的操作。除了上述示範的方法外,Django 還為我們提供了大量其它的方法,這些方法有一部分會在教程中使用,用到時我會講解它們的用法。但以後你開發自己的項目時,你就需要通過閱讀 Django 的官方文檔 來瞭解有哪些方法可用以及如何使用它們。
以上這篇使用python和Django完成部落格資料庫的遷移方法就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援幫客之家。