Django第4天

ORM簡(jiǎn)介

ORM,全拼Object-Relation Mapping,中文意為對(duì)象-關(guān)系映射,是隨著面向?qū)ο蟮能浖_發(fā)方法發(fā)展而產(chǎn)生的。面向?qū)ο蟮拈_發(fā)方法是當(dāng)今企業(yè)級(jí)應(yīng)用開發(fā)環(huán)境中的主流開發(fā)方法摘能,關(guān)系數(shù)據(jù)庫是企業(yè)級(jí)應(yīng)用環(huán)境中永久存放數(shù)據(jù)的主流數(shù)據(jù)存儲(chǔ)系統(tǒng)。對(duì)象和關(guān)系數(shù)據(jù)是業(yè)務(wù)實(shí)體的兩種表現(xiàn)形式即寡,業(yè)務(wù)實(shí)體在內(nèi)存中表現(xiàn)為對(duì)象徊哑,在數(shù)據(jù)庫中表現(xiàn)為關(guān)系數(shù)據(jù)。內(nèi)存中的對(duì)象之間存在關(guān)聯(lián)和繼承關(guān)系聪富,而在數(shù)據(jù)庫中莺丑,關(guān)系數(shù)據(jù)無法直接表達(dá)多對(duì)多關(guān)聯(lián)和繼承關(guān)系。因此墩蔓,對(duì)象-關(guān)系映射ORM系統(tǒng)一般以中間件的形式存在梢莽,主要實(shí)現(xiàn)程序?qū)ο蟮疥P(guān)系數(shù)據(jù)庫數(shù)據(jù)的映射。面向?qū)ο笫菑能浖こ袒驹瓌t(如耦合奸披、聚合昏名、封裝)的基礎(chǔ)上發(fā)展起來的,而關(guān)系數(shù)據(jù)庫則是從數(shù)學(xué)理論發(fā)展而來的阵面,兩套理論存在顯著的區(qū)別轻局。為了解決這個(gè)不匹配的現(xiàn)象,對(duì)象關(guān)系映射技術(shù)應(yīng)運(yùn)而生洪鸭。O/R中字母O起源于"對(duì)象"(Object),而R則來自于"關(guān)系"(Relational)。幾乎所有的程序里面仑扑,都存在對(duì)象和關(guān)系數(shù)據(jù)庫览爵。在業(yè)務(wù)邏輯層和用戶界面層中,我們是面向?qū)ο蟮恼蛞.?dāng)對(duì)象信息發(fā)生變化的時(shí)候蜓竹,我們需要把對(duì)象的信息保存在關(guān)系數(shù)據(jù)庫中。目前流行的ORM產(chǎn)品如Java的Hibernate储藐,.Net的EntityFormerWork等俱济。

在MVC框架中的Model模塊中都包括ORM,對(duì)于開發(fā)人員主要帶來了如下好處:

  • 實(shí)現(xiàn)了數(shù)據(jù)模型與數(shù)據(jù)庫的解耦钙勃,通過簡(jiǎn)單的配置就可以輕松更換數(shù)據(jù)庫蛛碌,而不需要修改代碼。
  • 只需要面向?qū)ο缶幊谭温疲恍枰嫦驍?shù)據(jù)庫編寫代碼左医。
  • 在MVC中Model中定義的類,通過ORM與關(guān)系型數(shù)據(jù)庫中的表對(duì)應(yīng)同木,對(duì)象的屬性體現(xiàn)對(duì)象間的關(guān)系,這種關(guān)系也被映射到數(shù)據(jù)表中跛十。

Django框架中ORM示意圖如下:


詳解模型類

定義屬性

Django根據(jù)屬性的類型確定以下信息:

  • 當(dāng)前選擇的數(shù)據(jù)庫支持字段的類型
  • 渲染管理表單時(shí)使用的默認(rèn)html控件
  • 在管理站點(diǎn)最低限度的驗(yàn)證

django會(huì)為表創(chuàng)建自動(dòng)增長的主鍵列彤路,每個(gè)模型只能有一個(gè)主鍵列,如果使用選項(xiàng)設(shè)置某屬性為主鍵列后django不會(huì)再創(chuàng)建自動(dòng)增長的主鍵列芥映。

默認(rèn)創(chuàng)建的主鍵列屬性為id洲尊,可以使用pk代替,pk全拼為primary key奈偏。

注意:pk是主鍵的別名坞嘀,若主鍵名為id2,那么pk是id2的別名惊来。

屬性命名限制:

  • 不能是python的保留關(guān)鍵字丽涩。
  • 不允許使用連續(xù)的下劃線,這是由django的查詢方式?jīng)Q定的裁蚁,以后會(huì)詳細(xì)講解查詢矢渊。
  • 定義屬性時(shí)需要指定字段類型,通過字段類型的參數(shù)指定選項(xiàng)枉证,語法如下:
屬性=models.字段類型(選項(xiàng))

字段類型

使用時(shí)需要引入django.db.models包矮男,字段類型如下:

  • AutoField:自動(dòng)增長的IntegerField,通常不用指定室谚,不指定時(shí)Django會(huì)自動(dòng)創(chuàng)建屬性名為id的自動(dòng)增長屬性毡鉴。
  • BooleanField:布爾字段崔泵,值為True或False。
  • NullBooleanField:支持Null猪瞬、True管削、False三種值。
  • CharField(max_length=字符長度):字符串撑螺。參數(shù)max_length表示最大字符個(gè)數(shù)含思。
  • TextField:大文本字段,一般超過4000個(gè)字符時(shí)使用甘晤。
  • IntegerField:整數(shù)含潘。
  • DecimalField(max_digits=None, decimal_places=None):十進(jìn)制浮點(diǎn)數(shù)。參數(shù)max_digits表示總位數(shù)线婚。參數(shù)decimal_places表示小數(shù)位數(shù)遏弱。
  • FloatField:浮點(diǎn)數(shù)。
  • DateField[auto_now=False, auto_now_add=False]):日期塞弊。
    • 1.參數(shù)auto_now表示每次保存對(duì)象時(shí)漱逸,自動(dòng)設(shè)置該字段為當(dāng)前時(shí)間,用于"最后一次修改"的時(shí)間戳游沿,它總是使用當(dāng)前日期饰抒,默認(rèn)為false。
    • 2.參數(shù)auto_now_add表示當(dāng)對(duì)象第一次被創(chuàng)建時(shí)自動(dòng)設(shè)置當(dāng)前時(shí)間诀黍,用于創(chuàng)建的時(shí)間戳袋坑,它總是使用當(dāng)前日期,默認(rèn)為false眯勾。

注:參數(shù)auto_now_add和auto_now是相互排斥的枣宫,組合將會(huì)發(fā)生錯(cuò)誤。

  • TimeField:時(shí)間吃环,參數(shù)同DateField也颤。
  • DateTimeField:日期時(shí)間,參數(shù)同DateField郁轻。
  • FileField:上傳文件字段翅娶。
  • ImageField:繼承于FileField,對(duì)上傳的內(nèi)容進(jìn)行校驗(yàn)范咨,確保是有效的圖片故觅。

選項(xiàng)

通過選項(xiàng)實(shí)現(xiàn)對(duì)字段的約束,選項(xiàng)如下:

  • null:如果為True渠啊,表示允許為空输吏,默認(rèn)值是False。
  • blank:如果為True替蛉,則該字段允許為空白贯溅,默認(rèn)值是False拄氯。

對(duì)比:null是數(shù)據(jù)庫范疇的概念,blank是表單驗(yàn)證范疇的它浅。

  • db_column:字段的名稱译柏,如果未指定,則使用屬性的名稱姐霍。
  • db_index:若值為True, 則在表中會(huì)為此字段創(chuàng)建索引鄙麦,默認(rèn)值是False。
  • default:默認(rèn)值镊折。
  • primary_key:若為True胯府,則該字段會(huì)成為模型的主鍵字段,默認(rèn)值是False恨胚,一般作為AutoField的選項(xiàng)使用骂因。
  • unique:如果為True, 這個(gè)字段在表中必須有唯一值,默認(rèn)值是False赃泡。

字段查詢

實(shí)現(xiàn)sql中where的功能寒波,調(diào)用過濾器filter()、exclude()升熊、get()俄烁,下面以filter()為例。

通過"屬性名_id"表示外鍵對(duì)應(yīng)對(duì)象的id值僚碎。

語法如下:

說明:屬性名稱和比較運(yùn)算符間使用兩個(gè)下劃線猴娩,所以屬性名不能包括多個(gè)下劃線。

屬性名稱__比較運(yùn)算符=值
條件運(yùn)算符
  1. 查詢等
    exact:表示判等勺阐。
    例:查詢編號(hào)為1的圖書。
list=BookInfo.objects.filter(id__exact=1)
可簡(jiǎn)寫為:
list=BookInfo.objects.filter(id=1)
  1. 模糊查詢
    說明:如果要包含%無需轉(zhuǎn)義矛双,直接寫即可渊抽。
    例:查詢書名包含'神'的圖書。
list = BookInfo.objects.filter(btitle__contains='神')
  1. startswith议忽、endswith:以指定值開頭或結(jié)尾懒闷。
    例:查詢書名以'部'結(jié)尾的圖書
list = BookInfo.objects.filter(btitle__endswith='部')

以上運(yùn)算符都區(qū)分大小寫,在這些運(yùn)算符前加上i表示不區(qū)分大小寫栈幸,如iexact愤估、icontains、istartswith速址、iendswith

條件字段查詢

實(shí)現(xiàn)sql中where的功能玩焰,調(diào)用過濾器filter()、exclude()芍锚、get()昔园,下面以filter()為例蔓榄。

通過"屬性名_id"表示外鍵對(duì)應(yīng)對(duì)象的id值。

語法同上

配置mysql的數(shù)據(jù)庫日志

查看mysql數(shù)據(jù)庫日志可以查看對(duì)數(shù)據(jù)庫的操作記錄默刚。 mysql日志文件默認(rèn)沒有產(chǎn)生甥郑,需要做如下配置:
右鍵Navicat數(shù)據(jù)庫選擇運(yùn)行命令行界面:

show variables like "general_log%"; 

命令查看日志文件是否打開 如圖所示:


如果 general_log 的 Value 為OFF
則需要輸入命令:

SET GLOBAL general_log = 'ON';

日志的默認(rèn)位置在:/usr/local/mysql/data/zhangyus-MacBook-Pro.log
在terminal下運(yùn)行上面的命令:sudo tail -f /usr/local/mysql/data/zhangyus-MacBook-Pro.log

條件運(yùn)算符
  1. 詢等
    exact:表示判等。
    例:查詢編號(hào)為1的圖書荤西。
    運(yùn)行
python manage.py shell
from booktest.models import *
BookInfo.objects.filter(id__exact=1)
可簡(jiǎn)寫為:
BookInfo.objects.filter(id=1)

在日志文件中會(huì)生成如下sql語句

SELECT `booktest_bookinfo`.`id`, `booktest_bookinfo`.`btitle`, `booktest_bookinfo`.`bpub_date`, `booktest_bookinfo`.`bread`, `booktest_bookinfo`.`bcomment`, `booktest_bookinfo`.`isDelete` FROM `booktest_bookinfo` WHERE `booktest_bookinfo`.`id` = 1
  1. 模糊查詢
  • contains:是否包含澜搅。
    說明:如果要包含%無需轉(zhuǎn)義,直接寫即可邪锌。
    例:查詢書名包含'英雄'的圖書勉躺。
BookInfo.objects.filter(btitle__contains='英雄')

在日志文件中會(huì)生成如下sql語句

SELECT `booktest_bookinfo`.`id`, `booktest_bookinfo`.`btitle`, `booktest_bookinfo`.`bpub_date`, `booktest_bookinfo`.`bread`, `booktest_bookinfo`.`bcomment`, `booktest_bookinfo`.`isDelete` FROM `booktest_bookinfo` WHERE `booktest_bookinfo`.`btitle` LIKE BINARY '%英雄%'
  • startswith、endswith:以指定值開頭或結(jié)尾秃流。
    例:查詢書名以'部'結(jié)尾的圖書
 BookInfo.objects.filter(btitle__endswith='部')

以上運(yùn)算符都區(qū)分大小寫赂蕴,在這些運(yùn)算符前加上i表示不區(qū)分大小寫,如iexact舶胀、icontains概说、istartswith、iendswith.

  1. 空查詢
    isnull:是否為null嚣伐。
    例:查詢書名不為空的圖書糖赔。
BookInfo.objects.filter(btitle__isnull=False)
  1. 范圍查詢
    in:是否包含在范圍內(nèi)。
    例:查詢編號(hào)為1或3或5的圖書
BookInfo.objects.filter(id__in=[1, 3, 5])
  1. 比較查詢
    gt轩端、gte放典、lt、lte:大于基茵、大于等于奋构、小于、小于等于拱层。
    例:查詢編號(hào)大于3的圖書
BookInfo.objects.filter(id__gt=3)
  1. 日期查詢
    year弥臼、month、day根灯、week_day径缅、hour、minute烙肺、second:對(duì)日期時(shí)間類型的屬性進(jìn)行運(yùn)算纳猪。

例:查詢1980年發(fā)表的圖書。

BookInfo.objects.filter(bpub_date__year=1980)

例:查詢1980年1月1日后發(fā)表的圖書桃笙。

BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1))
F對(duì)象

之前的查詢都是對(duì)象的屬性與常量值比較氏堤,兩個(gè)屬性怎么比較呢? 答:使用F對(duì)象怎栽,被定義在django.db.models中丽猬。

語法如下:

F(屬性名)

例:查詢閱讀量大于等于評(píng)論量的圖書宿饱。

from django.db.models import F
BookInfo.objects.filter(bread__gte=F('bcomment'))

可以在F對(duì)象上使用算數(shù)運(yùn)算。
例:查詢閱讀量大于2倍評(píng)論量的圖書脚祟。

BookInfo.objects.filter(bread__gt=F('bcomment') * 2)
Q對(duì)象

多個(gè)過濾器逐個(gè)調(diào)用表示邏輯與關(guān)系谬以,同sql語句中where部分的and關(guān)鍵字。
例:查詢閱讀量大于20由桌,并且編號(hào)小于3的圖書为黎。

BookInfo.objects.filter(bread__gt=20,id__lt=3)
或
BookInfo.objects.filter(bread__gt=20).filter(id__lt=3)

如果需要實(shí)現(xiàn)邏輯或or的查詢,需要使用Q()對(duì)象結(jié)合|運(yùn)算符行您,Q對(duì)象被義在django.db.models中铭乾。

語法如下:

Q(屬性名__運(yùn)算符=值)

Q對(duì)象可以使用&、|連接娃循,&表示邏輯與炕檩,|表示邏輯或。
例:查詢閱讀量大于20捌斧,或編號(hào)小于3的圖書笛质,只能使用Q對(duì)象實(shí)現(xiàn)

BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))

Q對(duì)象前可以使用~操作符,表示非not捞蚂。
例:查詢編號(hào)不等于3的圖書妇押。

BookInfo.objects.filter(~Q(pk=3))
聚合函數(shù)

使用aggregate()過濾器調(diào)用聚合函數(shù)。聚合函數(shù)包括:Avg姓迅,Count敲霍,Max,Min丁存,Sum肩杈,被定義在django.db.models中。
例:查詢圖書的總閱讀量

from django.db.models import Sum
BookInfo.objects.aggregate(Sum('bread'))

注意aggregate的返回值是一個(gè)字典類型解寝,格式如下:

 {'聚合類小寫__屬性名':值}
  如:{'sum__bread':3}

使用count時(shí)一般不使用aggregate()過濾器锋恬。
例:查詢圖書總數(shù)

from django.db.models import Count
BookInfo.objects.count()

注意count函數(shù)的返回值是一個(gè)數(shù)字。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末编丘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子彤悔,更是在濱河造成了極大的恐慌嘉抓,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晕窑,死亡現(xiàn)場(chǎng)離奇詭異抑片,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)杨赤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門敞斋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來截汪,“玉大人,你說我怎么就攤上這事植捎⊙媒猓” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵焰枢,是天一觀的道長蚓峦。 經(jīng)常有香客問我,道長济锄,這世上最難降的妖魔是什么暑椰? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮荐绝,結(jié)果婚禮上一汽,老公的妹妹穿的比我還像新娘。我一直安慰自己低滩,他們只是感情好召夹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著委造,像睡著了一般戳鹅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上昏兆,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天枫虏,我揣著相機(jī)與錄音,去河邊找鬼爬虱。 笑死隶债,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的跑筝。 我是一名探鬼主播死讹,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼曲梗!你這毒婦竟也來了赞警?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤虏两,失蹤者是張志新(化名)和其女友劉穎愧旦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體定罢,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笤虫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琼蚯。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酬凳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遭庶,到底是詐尸還是另有隱情宁仔,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布罚拟,位于F島的核電站台诗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏赐俗。R本人自食惡果不足惜拉队,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阻逮。 院中可真熱鬧粱快,春花似錦、人聲如沸叔扼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓜富。三九已至鳍咱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間与柑,已是汗流浹背谤辜。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留价捧,地道東北人丑念。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像结蟋,于是被迫代替她去往敵國和親脯倚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

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