django 入門筆記:數(shù)據(jù)模型

django 及 rest_framework 筆記鏈接如下:
django 入門筆記:環(huán)境及項(xiàng)目搭建
django 入門筆記:數(shù)據(jù)模型
django 入門筆記:視圖及模版
django 入門筆記:Admin 管理系統(tǒng)及表單
django 入門筆記:通用視圖類重構(gòu)視圖
django_rest_framework 入門筆記:Serializer
django_rest_framework 入門筆記:視圖函數(shù)重構(gòu)
django_rest_framework 入門筆記:分頁(yè)轩触,多條件篩選及權(quán)限認(rèn)證設(shè)置
django 自帶 user 字段擴(kuò)展及頭像上傳

上一部分我們介紹了環(huán)境和項(xiàng)目的搭建,以及數(shù)據(jù)庫(kù)的配置脱柱,那這一部分我們介紹和數(shù)據(jù)庫(kù)相關(guān)方面的知識(shí) -- 模型

創(chuàng)建 django 模型

我們需要在 "blog" 應(yīng)用下的 models.py 文件中添加 django 數(shù)據(jù)庫(kù)模型伐弹,模型類需要繼承 models.Model 類,例如

from django.db import models
class Category(models.Model):
    # 可以通過(guò)第一個(gè)參數(shù)傳入字符串設(shè)置別名
    name = models.CharField("分類", max_length=100)

    # 查找 Category 時(shí)榨为,返回為一個(gè) object 如果不重寫 __str__ 方法返回?cái)?shù)據(jù)直接顯示 Category Object掸茅,
    # 重寫該方法后,查找返回結(jié)果為該方法返回的值
    def __str__(self):
        return '<Category>[{}]'.format(self.name)
        
    # 通過(guò) Meta 來(lái)修改數(shù)據(jù)表的信息
    class Meta:
        db_table = "category" # 修改數(shù)據(jù)庫(kù)表名柠逞,默認(rèn)表名會(huì)是 項(xiàng)目名_模型名 blog_category
        ordering =  ['-id'] # 修改排序方式,"-" 表示逆序

Model 的常用字段類型還是比較多的景馁,下面將介紹常用的字段類型和關(guān)系類型板壮,以及字段類型的限制參數(shù)。

Model 的常用字段類型
  1. models.AutoField 自增列 如果沒(méi)有的話合住,默認(rèn)會(huì)生成一個(gè)名稱為 id 的列绰精,如果要顯示的自定義一個(gè)自增列,必須將給列設(shè)置為主鍵 primary_key=True
  2. models.CharField  字符串  指定 max_length 參數(shù)設(shè)置最大長(zhǎng)度
  3. models.BooleanField  布爾類型
  4. models.DateField  日期類型 對(duì)于參數(shù)透葛,auto_now = True 則每次更新都會(huì)更新這個(gè)時(shí)間笨使,auto_now_add 則只是第一次創(chuàng)建添加,之后的更新不再改變
  5. models.DateTimeField  日期類型 同 models.DateField
  6. models.EmailField  字符串類型(正則表達(dá)式郵箱)
  7. models.FloatField  浮點(diǎn)類型
  8. models.IntegerField  整型
  9. models.BigIntegerField  長(zhǎng)整型
  10. models.IPAddressField  字符串類型(ip4正則表達(dá)式)
  11. models.GenericIPAddressField  字符串類型(ip4和ip6是可選的) 參數(shù)protocol可以是:both僚害、ipv4硫椰、ipv6
  12. models.TextField  字符串類型 同 CharField, 可以設(shè)置更長(zhǎng)的字符串
  13. models.TimeField  時(shí)間 HH:MM[:ss[.uuuuuu]]
  14. models.URLField  字符串萨蚕,地址正則表達(dá)式
  15. models.ImageField 圖片類型
  16. models.FilePathField 文件類型
Model 的連表結(jié)構(gòu)
  1. 一對(duì)多:models.ForeignKey(其他表) 例如 ModelA 中有個(gè)字段指向 ModelB

    # 最好加上 on_delete 屬性, 否則可能會(huì)報(bào)錯(cuò)
    b = models.ForeignKey(ModelB靶草,on_delete=models.CASCAED)
    

    ModelA 為”多“,ModelB 為”一“

  2. 多對(duì)多:models.ManyToManyField(其他表) 例如 ModelA 中有個(gè)字段指向 ModelB

    bs = models.ManyToManyField(ModelB)
    

    ModelA 可以對(duì)應(yīng)多個(gè) ModelB 的值岳遥,同樣 ModelB 可以對(duì)應(yīng)多個(gè) ModelA 的值

  3. 一對(duì)一:models.OneToOneField(其他表) 例如 ModelA 中有字段指向 ModelB

    b = models.OneToOneField(ModelB)
    

    ModelA 只能對(duì)應(yīng) ModelB 中特定的值奕翔,同樣 ModelB 也只能對(duì)應(yīng) ModelA 中特定的值

Model 的常用設(shè)置參數(shù)
  1. null=(True/False) 數(shù)據(jù)庫(kù)中字段是否可以為空
  2. blank=(True/False) django的 Admin 中添加數(shù)據(jù)時(shí)是否可允許空值
  3. primary_key=(True/False) 主鍵,對(duì) AutoField 設(shè)置主鍵后浩蓉,就會(huì)代替原來(lái)的自增 id 列
  4. auto_now=(True/False) 自動(dòng)創(chuàng)建---無(wú)論添加或修改派继,都是當(dāng)前操作的時(shí)間,在 MySql 下存在過(guò)濾月份時(shí)候數(shù)據(jù)為空捻艳,解決方案參考 MySql 文檔 Section 10.6
  5. auto_now_add=(True/False) 自動(dòng)創(chuàng)建---永遠(yuǎn)是創(chuàng)建時(shí)的時(shí)間
  6. choices=(xx,xx,xx) 可選擇列表項(xiàng)驾窟,通常是一個(gè)列表或者元組
  7. max_length=(int) 最大長(zhǎng)度,多和字符串類型配合使用
  8. verbose_name='xxxx' Admin 中字段的顯示名稱
  9. name|db_column 數(shù)據(jù)庫(kù)中的字段名稱
  10. unique=(True/False) 是否可以重復(fù)
  11. db_index=(True/False) 是否設(shè)置為索引
  12. editable=(True/False) 在Admin里是否可編輯
  13. error_messages='xxxx' 錯(cuò)誤提示
  14. auto_created=(True/False) 是否自動(dòng)創(chuàng)建
  15. help_text='xxxx' 在 Admin 中提示幫助信息
  16. upload-to='xxxx' 上傳到哪個(gè)位置认轨,與 ImageField,FfileField 配合使用

創(chuàng)建完模型后纫普,我們需要根據(jù)模型來(lái)創(chuàng)建數(shù)據(jù)庫(kù),設(shè)計(jì)到數(shù)據(jù)庫(kù)遷移的知識(shí)

數(shù)據(jù)庫(kù)的遷移

我們通過(guò)命令行切換到 manage.py 文件夾,分別運(yùn)行如下命令行

  1. python manage.py makemigrations 運(yùn)行后會(huì)在相應(yīng)應(yīng)用下的 migrations 目錄生成一個(gè) 0001_initial.py(0001會(huì)根據(jù)遷移的次數(shù)進(jìn)行遞增)昨稼,用于記錄對(duì)模型的修改
  2. python manage.py migrate 運(yùn)行后將 model 中的操作轉(zhuǎn)換成為數(shù)據(jù)庫(kù)語(yǔ)言节视,作用于數(shù)據(jù)庫(kù),對(duì)數(shù)據(jù)庫(kù)進(jìn)行相應(yīng)的修改
    如果對(duì)命令行做了什么動(dòng)作假栓,我們可以通過(guò)運(yùn)行如下命令行查看具體的數(shù)據(jù)庫(kù)操作python manage.py sqlmigrate blog 0001 其中 blog 0001 根據(jù)實(shí)際項(xiàng)目進(jìn)行替換
數(shù)據(jù)庫(kù)插入數(shù)據(jù)

創(chuàng)建好數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)添加寻行,可以通過(guò)如下操作進(jìn)行

from blog.models import Category, Tag
c = Category('test category')
c.save()
t = Tag('test tag')
t.save()

打開數(shù)據(jù)庫(kù)可以看到插入的數(shù)據(jù)

數(shù)據(jù)庫(kù)查找數(shù)據(jù)

插入數(shù)據(jù)后,查找數(shù)據(jù)庫(kù)內(nèi)的數(shù)據(jù)可以通過(guò)如下操作進(jìn)行

# 查找某個(gè)表所有的數(shù)據(jù)匾荆,返回<QuerySet[...]>
from blog.models import Category
c_list = Category.objects.all()
# 查找某個(gè)特定的數(shù)據(jù)拌蜘,如果數(shù)據(jù)不存在會(huì)拋出錯(cuò)誤 blog.models.DoesNotExist澜搅,
# 存在則返回 Object垫蛆,如果重寫了 __str__ 方法什燕,則返回該方法所指定的值
c_test = Category.objects.get(name='test category')
# 也可以通過(guò) filter 關(guān)鍵詞進(jìn)行查找
c_test = Category.objects.filter(name='test category, id__lt=10)
c_test = Category.objects.filter(id__range=[0, 10])
# 還可以使用 startswith皮胡,istartswith, endswith, iendswith 等條件
# .values() 和 .values_list() 區(qū)別
# .values() 取出某一列咬荷,每個(gè)元素是一個(gè)字典胁编,.values_list() 取出的元素是一個(gè)個(gè)元組
# 如下語(yǔ)句得到的結(jié)果為 <QuerySet [{'name': 'test category', 'id': 1}]>
print(Category.objects.filter(name='test category').values('name', 'id')) 
# 如下語(yǔ)句得到的結(jié)果為 <QuerySet [('test category', 1)]>
print(Category.objects.filter(name='test category').values_list('name', 'id'))
# exclude 查詢條件外的數(shù)據(jù)
Category.objects.exclude(id__gt=2)   即查找 id 不大于 2 的數(shù)據(jù)
# 通過(guò) order_by 進(jìn)行排序
Category.objects.all().order_by('-id') # 逆序排序馒稍,逆序排序只需要在排序字段前加"-"號(hào)即可
# 刪選某個(gè)范圍內(nèi)的數(shù)據(jù) 類似于 SQL 語(yǔ)句中的 OFFSET 10 LIMIT 10
Category.objects.all()[10: 20] # 獲取列表中 10-20 的數(shù)據(jù)
# aggregate 操作符(出了求和 Count 還有 Avg, Max, Min 等礁哄,通過(guò) django.db.models 導(dǎo)入)
print(Category.objects.aggregate(Count('name')))    # {'name__count': 5}
# 也可以指定結(jié)合后的字段名
print(Category.objects.aggregate(category_count=Count('name)))  # {'category_count': 5}
# annotate 操作符
# 假設(shè) Post 表中有個(gè)字段指向 Category
# category = models.ForeignKey(Category) 在表 Category 中需要統(tǒng)計(jì)某個(gè) category 下 post 數(shù)量构罗,
# 但是表 Category 中沒(méi)有 post_count 字段铜涉,那么可以通過(guò) annotate 操作符來(lái)進(jìn)行統(tǒng)計(jì)
c_list = Category.objects.annotate(post_count=Count('post'))
print(c_list[0].post_count) # 12
# "__" 的操作
# 大于,小于操作
Categroy.objects.fileter(id__gt=1, id__lt=10) # 查找 id 介于 1 和 10 之間的數(shù)據(jù)
# in
Category.objects.filter(id__in=[11, 22, 33]) # 查找 id 為 11遂唧,22芙代,33 的值
Category.objects.exclude(id__in=[11, 22, 33]) # not in
# contains
Category.objects.filter(name__contains="test") 查找 name 字段包含 test 的值
Category.objects.filter(name__icontains="test") # 大小寫不敏感
# range
Caregory.objects.filter(id__range=[1, 10]) # 查找 id 介于 1 和 10 之間的數(shù)據(jù),即 between and
# 類似的包括 startwith, istartwith, endwith, iendwith 等
數(shù)據(jù)庫(kù)修改數(shù)據(jù)

對(duì)存在的數(shù)據(jù)進(jìn)行修改盖彭,可通過(guò)如下操作進(jìn)行

c = Category.objects.get(name='test category')
c.name = 'new test category'
c.save()
刪除數(shù)據(jù)庫(kù)數(shù)據(jù)

對(duì)存在數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行刪除纹烹,可以通過(guò)如下操作進(jìn)行

# 刪除某條特定的數(shù)據(jù)
c = Category.objects.get(name='new test category')
c.delete()
# 刪除全部的數(shù)據(jù)
c_list = Category.objects.get()
for c in c_list:
    c.delete()

更多的數(shù)據(jù)庫(kù)操作 API 查看官方的 API django 數(shù)據(jù)庫(kù)操作 API

使用原生 SQL 語(yǔ)句操作數(shù)據(jù)庫(kù)

django 支持使用原生語(yǔ)句操作數(shù)據(jù)庫(kù)

from django.db import connection
cursor = connection.cursor()
# 原生 SQL 語(yǔ)句放在 execute 中使用
cursor.execute("SELECT c.id, c.name FROM blog_category as c")
# 獲取查詢到的第一個(gè)數(shù)據(jù)
row = cursor.fetchone()
# 獲取全部查詢到的數(shù)據(jù)
rows = cursor.fetchall()

最后附上整個(gè)項(xiàng)目的地址:blog_project

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市召边,隨后出現(xiàn)的幾起案子滔韵,更是在濱河造成了極大的恐慌,老刑警劉巖掌实,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陪蜻,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贱鼻,警方通過(guò)查閱死者的電腦和手機(jī)宴卖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)邻悬,“玉大人症昏,你說(shuō)我怎么就攤上這事「阜幔” “怎么了肝谭?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵掘宪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我攘烛,道長(zhǎng)魏滚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任坟漱,我火速辦了婚禮鼠次,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘芋齿。我一直安慰自己腥寇,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布觅捆。 她就那樣靜靜地躺著赦役,像睡著了一般。 火紅的嫁衣襯著肌膚如雪栅炒。 梳的紋絲不亂的頭發(fā)上掂摔,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音职辅,去河邊找鬼。 笑死聂示,一個(gè)胖子當(dāng)著我的面吹牛域携,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鱼喉,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼秀鞭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了扛禽?” 一聲冷哼從身側(cè)響起锋边,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎编曼,沒(méi)想到半個(gè)月后豆巨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掐场,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年往扔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熊户。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萍膛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嚷堡,到底是詐尸還是另有隱情蝗罗,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站串塑,受9級(jí)特大地震影響沼琉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拟赊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一刺桃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吸祟,春花似錦瑟慈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至过吻,卻和暖如春进泼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纤虽。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工乳绕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人逼纸。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓洋措,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親杰刽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子菠发,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

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