Django 學習筆記之模型(上)

題圖:by thefolkpr0ject from Instagram

上片文章講解模板。你本文將講解 “MTV” 中 M 層次泌类,即模型層(數(shù)據(jù)存取層)。模型這內(nèi)容比較多底燎,我將其拆分為 3 個部分來講解刃榨。同時,文章也配套了例子双仍,你可以通過 閱讀原文 來查看枢希。

0 編程環(huán)境

因為 Django 近期推出 Django 2.0 版本, 所以有必要再說明下殊校。如果你是按照本系列來學習 Django 框架的話晴玖,按照前面安裝 Django 的方式,你安裝 Django 版本應該是最新版本为流,即 2.0呕屎。

那么使用最新 Django 版本來學習可以嗎?如果是學習的話敬察,不用太在意版本秀睛。當然學習最新的較好,因為可以學習新的 API莲祸。同時蹂安,Django 2.0 不再兼容 Python 2 了,現(xiàn)在學習 Python 都建議采用 Python 3版本了锐帜。另外 Django 1.8 官方只維護到 2018 年的 4 月田盈,1.11 是最后一個兼容 Python 2 的 Django版本。如果是項目需要升級 Django版本缴阎,需要兼容到 Python 2允瞧,那么要考慮用 1.11 版本了。

順便補充下本文用的一些工具的版本:Python 版本是 3.6,Mysql 版本是 5.5.

1 模型是什么

在 Web 應用中述暂,數(shù)據(jù)一般存儲到數(shù)據(jù)庫中痹升。Django 中的模型層是跟數(shù)據(jù)庫打交道的層次。模型層中可能會有多個模型畦韭,每個模型(每個 app 中的 models.py 中每個類都是一個模型)都對應著數(shù)據(jù)庫中的唯一一張表疼蛾。

2 配置數(shù)據(jù)庫

在我們探索 Django 的模型層之前,我們需要配置下數(shù)據(jù)庫艺配;告訴 Django 視野什么數(shù)據(jù)庫以及如何連接數(shù)據(jù)庫察郁。這一步要確保配置無誤,不然后面難以執(zhí)行妒挎。我們找到新項目中的 setting.py, 里面有個 DATABASES 選項绳锅。Django 默認是使用 sqlite 數(shù)據(jù)庫,所以你會看到里面 sqlite 數(shù)據(jù)庫的配置信息酝掩。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

上面的代碼中的 ENGINE 是選擇哪個數(shù)據(jù)庫引擎, NAME 是數(shù)據(jù)庫的名字鳞芙。至于選擇哪種引擎,要看項目中使用了什么數(shù)據(jù)庫期虾。Django 目前支持以下這 MySQL原朝、PostgreSQL、Oracle 等數(shù)據(jù)庫镶苞,它們的數(shù)據(jù)庫引擎設置如下:

設置字段 數(shù)據(jù)庫 設配器(驅(qū)動)
postgresql PostgreSQL psycopg 1.x版
postgresql_psycopg2 PostgreSQL psycopg 2.x版
mysql MySQL MySQLdb
sqlite3 SQLite 不需要
oracle Oracle cx_Oracle

其中設置字段是填充 ENGINE 的值喳坠。如果你使用的 MySQL 數(shù)據(jù)庫,那么你需要填寫 django.db.backends.mysql茂蚓。數(shù)據(jù)庫驅(qū)動表示需要使用 pip 安裝該庫壕鹉。如果你使用的 MySQL 數(shù)據(jù)庫,那么你需要安裝 MySQLdb 設配器聋涨。

但是這里有個坑晾浴,MySQLdb 在支持 Python 2 版本,不支持 Python 3 版本牍白。所以你安裝該設配器之后脊凰,運行項目會報出錯誤。Django 官網(wǎng)建議使用替代品 mysqlclient茂腥。mysqlclient 是 MySQLdb 的一個分支狸涌,最主要是它支持 Python 3。

本文中使用到 Mysql 數(shù)據(jù)庫最岗,那么 DATABASES 的配置如下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': '123456',
    }
}

3 第一個模型

我們先新建名為 Django_demo 的 projeact, 再新建名為 demo 的 app帕胆。最后,別忘記在 setting.py 中將新創(chuàng)建的 app 激活般渡。

# Django 2.0 的初始配置內(nèi)容
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'demo',  # 我們新創(chuàng)建的 app
]

3.1 創(chuàng)建模型

打開我們剛才創(chuàng)建的 app 中的 models.py 文件惶楼,我們以后就主要在這里編寫模型右蹦。假設現(xiàn)在有個需求:某個作者創(chuàng)作了一本書,本書由出版社出版了歼捐。我們可以設定三者的字段以及關(guān)系。

  • 假設作者有姓名晨汹、Email 郵箱這兩個數(shù)據(jù)屬性豹储。
  • 假設出版社有出版社名稱、地址這兩個屬性淘这。
  • 書籍有兩四個屬性:書名剥扣、出版日期、作者铝穷、出版社。有一個或多個作者(和作者是多對多的關(guān)聯(lián)關(guān)系[many-to-many])曙聂, 只有一個出版商(和出版商是一對多的關(guān)聯(lián)關(guān)系[one-to-many],也被稱作外鍵[foreign key])

所以我們編寫代碼如下:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=40)
    email = models.EmailField()

class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    # publisher = models.ForeignKey(Publisher)
    # Django 2.0 需要加上 on_delete=models.CASCADE
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
    publication_date = models.DateField()

我們定義每個模型断国,即類(如 Author 和 Book)都需要繼承 django.db.models.Model。Model 是 Django 做了一層包裝以便我們更加方便地使用的類榆苞, 它其中包含了所有數(shù)據(jù)庫交互的方法。上面代碼中的每個類相當于單個數(shù)據(jù)庫表坐漏,每個屬性也是這個表中的一個字段。 屬性名就是字段名赊琳,它的類型(例如 CharField )相當于數(shù)據(jù)庫的字段類型 (例如 varchar )街夭。例如, Publisher 模塊等同于下面這張表

CREATE TABLE "Publisher" (
    "id" serial NOT NULL PRIMARY KEY,
    "name" varchar(30) NOT NULL,
    "address" varchar(50) NOT NULL,
);

所以我們在為屬性命名的時候慨畸,要避免使用數(shù)據(jù)庫的關(guān)鍵字。另外檐什,我們只需要關(guān)心每個類的屬性以及長度限制弱卡,不用關(guān)心怎么創(chuàng)建數(shù)據(jù)庫表。Django 可以自動生成這些 CREATE TABLE 語句的瓮具。

3.1 創(chuàng)建數(shù)據(jù)表

我們上面的創(chuàng)建了幾個模型還處于定義上,Django 還沒有正真創(chuàng)建數(shù)據(jù)庫中的表名党。
因此传睹,我們需要執(zhí)行兩個命令來同步一下數(shù)據(jù)庫。

在我們剛才創(chuàng)建的工程 Django_demo 目錄下欧啤,我們打開終端邢隧,執(zhí)行以下命令:

python manage.py makemigrations

運行成功效果圖如下:


點擊查看大圖

這一步相當于 在該app下建立 migrations目錄,并記錄下你所有的關(guān)于modes.py的改動按摘,比如0001_initial.py迫靖, 但是這個改動還沒有作用到數(shù)據(jù)庫文件

第二步,在之前的終端上繼續(xù)執(zhí)行 migrate 命令系宜。

python manage.py migrate

運行成功效果圖如下:


點擊查看大圖

這一步表示將該改動(當makemigrations之后產(chǎn)生了0001_initial.py 文件)作用到數(shù)據(jù)庫文件盹牧,比如 create table 之類。

如果你用到 Pycharm 的 Database 功能汰寓,你會看到我們剛才創(chuàng)建的定義的幾個模型有滑。


點擊查看大圖

3.2 字段類型

在前面的例子中,我們需要對每個屬性設置一個字段望艺,例如 CharField肌访。Django 內(nèi)置了幾十種內(nèi)置字段類型。常用的類型如下:

  1. AutoField:一個根據(jù)實際ID自動增長的 IntegerField 惩激。如果表中沒有設置主鍵時,將會自動添加一個自增主鍵顷蟀。

2)IntegerField:一個整數(shù)。在 Django 所有支持的數(shù)據(jù)庫中哮兰,-2147483648 到 2147483647 范圍才是合法的喝滞。

3)BigIntegerField:一個64位整數(shù), 和 IntegerField 類似右遭,不過它的范圍比較大缤削。

4)BooleanField:一個 true/false 字段亭敢。這個字段的默認表單部件是 CheckboxInput。

5)CharField:字符字段帅刀。對于比較大的文本內(nèi)容,請使用 TextField 類型扣溺。這個字段的默認表單部件是 TextInput。它有個參數(shù) max_length腹纳。max_length 表示字段允許的最大字符串長度驱犹。這將在數(shù)據(jù)庫中和表單驗證時生效

6)TextField:大文本字段。默認的表單部件是一個 Textarea蛔钙。

7)DateField:日期荠医。它帶有兩個可選參數(shù):auto_now 和 auto_now_add桑涎。auto_now 表示當對象保存時兼贡,該字段會自動設置成當前時間。一般用于記錄“修改時間” 等曼。auto_now_add 記錄字段首次被創(chuàng)建的時間凿蒜。

8)DateTimeField:時間和日期。它也帶有兩個可選參數(shù)州泊,名字和用法跟 DateField 一樣漂洋。

9)TimeField:時間字段, 類似于Python datetime.time 實例. 和 DateField 具有相同的選項刽漂。

10)URLField:一個 CharField 類型的URL,默認長度是200贝咙;默認的表單部件是一個 TextInput颈畸。

11)EmailField:一個檢查輸入的email地址是否合法的 CharField 類型。

12)FileField:上傳文件字段礁苗。

13)ImageField:圖片字段徙缴,它繼承了 FileField 所以屬性和方法。

3.3 關(guān)系字段

關(guān)系字段(Relationship fileds) 也是屬于字段疏叨,只不過三個字段比較特殊穿剖,所以單獨拿出來說糊余。我們按照上述的創(chuàng)建模型的例子來繼續(xù)講解单寂。它們?nèi)咧g的關(guān)系應該這樣:一本書由一家出版社出版吐辙,一家出版社可以出版很多書。一本書由多個作者合寫尊沸,一個作者可以寫很多書贤惯。

1)ForeignKey
表示屬于模型間關(guān)系中的多對一關(guān)系孵构。在我們的范例模型中,一家出版社 publisher 可以出版很多書 Book。在數(shù)據(jù)庫中, Django 使用 ForeignKey 字段名稱+ "_id" 做為數(shù)據(jù)庫中的列名稱溯职。在上面的例子中, 書籍 model 對應的數(shù)據(jù)表中會有一個 publisher_id 列谜酒。你可以通過顯式地指定 db_column 來改變該字段的列名稱,不過,除非你想自定 義 SQL 粘驰,否則沒必要更改數(shù)據(jù)庫的列名稱述么。

它第一個參數(shù)必須傳入該模型關(guān)聯(lián)的類度秘。on_delete 現(xiàn)在可以用作第二個位置參數(shù)(之前它通常只是作為一個關(guān)鍵字參數(shù)傳遞). 在Django 2.0中,這將是一個必傳的參數(shù)剑梳。

2)OneToOneField
它屬于 ForeignKey 中的特例垢乙。當 ForeignKey 中有個字段 unique 被設置為 True 時, 就表示一對一關(guān)系酪刀。

3)ManyToManyField
屬于模型間關(guān)系中的多對多關(guān)系。在我們的范例模型中齐婴, Book 有一個 多對多字段 叫做 authors稠茂。因為他們的關(guān)系是一本書由多個作者合寫睬关,一個作者可以寫很多書。在數(shù)據(jù)庫中
Django 創(chuàng)建一個中間表來表示 ManyToManyField 關(guān)系丐箩。默認情況下,中間表的名稱由兩個關(guān)系表名結(jié)合而成施籍。所以剛才我們創(chuàng)建數(shù)據(jù)庫表的途中概漱,會有四張表瓤摧,而不是三表。

3.4 字段選項

有些字段會有些特殊參數(shù)腻异,但所有字段類型都又些通用的可選選項这揣。先是常用的可選選項。
1)null :如果該參數(shù)設置為 True这嚣,Django將會把數(shù)據(jù)庫中的空值保存為 NULL姐帚。不填寫就默認為 False障涯。

2)blank:如果為 True 膳汪,該字段允許為空值九秀,不填寫默認為 False鼓蜒。這個字段是用于處理表單數(shù)據(jù)輸入驗證。

3)primary_key:如果為 True娇豫,那么這個字段就是模型的主鍵畅厢。

4)unique:如果該值設置為 True, 這個數(shù)據(jù)字段在整張表中必須是唯一的框杜。

5)default:設置該字段的默認值。

6)由二項元組構(gòu)成的一個可迭代對象(列表或元組)椒振,用來給字段提供選擇項梧乘。 如果設置了 choices选调,默認的表單將是一個選擇框灵份。具體使用例子如下:

from django.db import models

class Person(models.Model):
    SHIRT_SIZES = (
        ('S', 'Small'),
        ('M', 'Medium'),
        ('L', 'Large'),
    )
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)

下篇文章填渠,我們將講解如果對這些模型(表)進行操作。
源碼地址

4 寫在最后

我新建一個 Python Web 學習交流 QQ 群莺葫,群號:701534112枪眉。歡迎大家加群,一起交流堡纬,一起學習烤镐,一起進步。


Python Web 學習交流群

往前 Django 學習筆記文章
Django 學習筆記之環(huán)境搭建
Django 學習筆記之初始
Django 學習筆記之視圖與URL配置
Django 學習筆記之模板


本文原創(chuàng)發(fā)布于微信公眾號「極客猴」碗旅,歡迎關(guān)注第一時間獲取更多原創(chuàng)分享

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扛芽,一起剝皮案震驚了整個濱河市川尖,隨后出現(xiàn)的幾起案子茫孔,更是在濱河造成了極大的恐慌,老刑警劉巖馍悟,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锣咒,死亡現(xiàn)場離奇詭異赞弥,居然都是意外死亡,警方通過查閱死者的電腦和手機悼嫉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門戏蔑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來总棵,“玉大人改含,你說我怎么就攤上這事∪谢剑” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵硬霍,是天一觀的道長唯卖。 經(jīng)常有香客問我躬柬,道長允青,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任法牲,我火速辦了婚禮拒垃,結(jié)果婚禮上瓷蛙,老公的妹妹穿的比我還像新娘。我一直安慰自己横堡,他們只是感情好姥宝,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布腊满。 她就那樣靜靜地躺著碳蛋,像睡著了一般省咨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笤受,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天箩兽,我揣著相機與錄音,去河邊找鬼身坐。 笑死落包,一個胖子當著我的面吹牛咐蝇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撮竿,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼幢踏,長吁一口氣:“原來是場噩夢啊……” “哼许师!你這毒婦竟也來了微渠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤檀蹋,失蹤者是張志新(化名)和其女友劉穎俯逾,沒想到半個月后舅逸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡坠七,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年彪置,在試婚紗的時候發(fā)現(xiàn)自己被綠了悉稠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡耀盗,死狀恐怖叛拷,靈堂內(nèi)的尸體忽然破棺而出岂却,到底是詐尸還是另有隱情,我是刑警寧澤署浩,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布筋栋,位于F島的核電站,受9級特大地震影響正驻,放射性物質(zhì)發(fā)生泄漏弊攘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一姑曙、第九天 我趴在偏房一處隱蔽的房頂上張望襟交。 院中可真熱鬧,春花似錦伤靠、人聲如沸捣域。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽焕梅。三九已至,卻和暖如春丘侠,著一層夾襖步出監(jiān)牢的瞬間徒欣,已是汗流浹背熬甚。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留醋寝,地道東北人甚亭。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像萨醒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容