Django之?dāng)?shù)據(jù)庫(kù)ORM基礎(chǔ)到進(jìn)階操作

一、準(zhǔn)備工作

表結(jié)構(gòu)如下:

from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    birth = models.DateField(auto_now = True)

    def __str__(self):
        return f'<Person obj:{self.id}{self.name}>'

class Publisher(models.Model):
    name = models.CharField(max_length=32)

    def __str__(self):
        return f'<Publisher obj:{self.id}{self.name}>'

class Book(models.Model):
    name = models.CharField(max_length = 32)
    price = models.DecimalField(max_digits=6,decimal_places=2)
    sale = models.IntegerField(default=-1)
    stock = models.IntegerField(default=-1)

    publisher = models.ForeignKey(to='Publisher')

    def __str__(self):
        return f'<Book obj:{self.id}{self.name}>'


class Author(models.Model):
    name = models.CharField(max_length=32)

    books = models.ManyToManyField('Book')

    def __str__(self):
        return f'<Author obj:{self.id}{self.name}>'

二师溅、ORM基本操作

1. 查詢
  • 查詢所有的出版社對(duì)象的集合
     models.Publisher.objects.all() 
    
  • 返回與所給篩選條件相匹配的對(duì)象胰锌,返回結(jié)果有且只有一個(gè),如果符合篩選條件的對(duì)象超過(guò)一個(gè)或者沒(méi)有都會(huì)拋出錯(cuò)誤脊奋。
     models.Publisher.objects.get(id=1)   
    
  • 查詢滿足條件的所有對(duì)象,返回對(duì)象列表
    models.Publisher.objects.filter(id=1,name='sss')  
    
  • 排序
    models.Publisher.objects.all().order_by('id')    
    
2.屬性查詢:
- 無(wú)外鍵病涨、多對(duì)多:
pub_obj.id
pub_obj.name
- 外鍵:
book_obj.publisher         //book所關(guān)聯(lián)的出版社對(duì)象
book_obj.publisher.id      //book所關(guān)聯(lián)的出版社對(duì)象id
book_obj.publisher_id     //book所關(guān)聯(lián)的出版社對(duì)象id
- 多對(duì)多:
author_obj.books         //django封裝的管理對(duì)象
author_obj.books.all()  //作者管理的所有書籍的對(duì)象列表
3. 增加
- 普通添加:
models.Publisher.objects.create(name='新的出版社')
- 外鍵:
models.Bookj.objects.create(name='新的書名',publisher_id=1)  //添加關(guān)聯(lián)對(duì)象id
models.Bookj.objects.create(name='新的書名',publisher=pub_obj)  //添加關(guān)聯(lián)對(duì)象
- 多對(duì)多:
autho_obj = models.Author.objects.create(name='新的作者')
autho_obj.books.set([1,2])  //關(guān)聯(lián)對(duì)象id列表
4. 刪除
models.Publisher.objects.get(id=1).delele()  //刪除特定對(duì)象
models.Publisher.objects.filter(name='xxx').delele()  //批量刪除
5. 修改
- 普通修改:
pub_obj.name = '新的名字'
pub_obj.save()   //這種修改方式在數(shù)據(jù)庫(kù)操作上會(huì)對(duì)所有字段重新賦值
- 外鍵:
book_obj.name = '新的書名'
book_obj.publisher = pub_obj  //基于對(duì)象添加
# book_obj.publisher_id = pub_obj.id  //基于關(guān)聯(lián)對(duì)象id添加
book_obj.save()
- 多對(duì)多:
author_obj.name='新的作者名'  //修改字段
author_obj.save()
author_obj.books.set([1,2,3])  //修改多對(duì)多關(guān)系

三富玷、ORM進(jìn)階操作

1. 一般操作

  • 必知必會(huì)13條:
    1、all()查詢所有
    ret = models.Person.objects.all()
    2没宾、get()返回與所給篩選條件相匹配的對(duì)象凌彬,返回結(jié)果有且只有一個(gè),如果符合篩選條件的對(duì)象超過(guò)一個(gè)或者沒(méi)有都會(huì)拋出錯(cuò)誤循衰。
    ret = models.Person.objects.get(id= 2)
    3铲敛、filter()它包含了與所給篩選條件相匹配的對(duì)象
    ret = models.Person.objects.filter(name='王計(jì)飛')
    ret = models.Person.objects.filter(name='哈哈')
    4、exclude()它包含了與所給篩選條件不匹配的對(duì)象
    ret = models.Author.objects.exclude(id=1)
    5会钝、values()返回一個(gè)ValueQuerySet——一個(gè)特殊的QuerySet伐蒋,運(yùn)行后得到的并不是一系列model的實(shí)例化對(duì)象,而是一個(gè)可迭代的字典序列
    ret = models.Publisher.objects.values('id','name')
    6迁酸、values_list()它與values()非常相似先鱼,它返回的是一個(gè)元組序列,values返回的是一個(gè)字典序列
    ret = models.Book.objects.values_list('id','name','price','sale','stock','publisher_id')
    7奸鬓、order_by()對(duì)查詢結(jié)果排序
    ret = models.Book.objects.all().order_by('sale')
    8焙畔、reverse()對(duì)查詢結(jié)果反向排序,請(qǐng)注意reverse()通常只能在具有已定義順序的QuerySet上調(diào)用(在model類的Meta中指定ordering或調(diào)用order_by()方法)串远。
    ret = models.Book.objects.all().order_by('price').reverse()
    9宏多、distinct()從返回結(jié)果中剔除重復(fù)紀(jì)錄(如果你查詢跨越多個(gè)表,可能在計(jì)算QuerySet時(shí)得到重復(fù)的結(jié)果澡罚。此時(shí)可以使用distinct()伸但,注意只有在PostgreSQL中支持按字段去重。)
    ret = models.Book.objects.values().distinct()
    10留搔、count()返回?cái)?shù)據(jù)庫(kù)中匹配查詢(QuerySet)的對(duì)象數(shù)量更胖。
    ret = models.Publisher.objects.all().count()
    11、first()返回第一條
    ret = models.Book.objects.first()
    12、last()返回最后一條
    ret = models.Book.objects.last()
    13却妨、exists()如果QuerySet包含數(shù)據(jù)饵逐,就返回True,否則返回False
    ret = models.Book.objects.filter(name='awefefe').exists()

2管呵、必知必會(huì)13條結(jié)果總結(jié):

- 返回QuerySet對(duì)象的方法有(6)
all()
filter()
exclude()
order_by()
reverse()
distinct()
- 特殊的QuerySet (2)
values() 返回一個(gè)可迭代的字典序列
values_list() 返回一個(gè)可迭代的元祖序列
- 返回具體對(duì)象的 (3)
get()
first()
last()
- 返回布爾值的方法有:(1)
exists()
- 返回?cái)?shù)字的方法有(1)
count()

3梳毙、單表查詢之神奇的雙下劃線

ret = models.Book.objects.filter(price__lt=50,price__gt=20) <大于小于>
ret = models.Book.objects.filter(price__in=[66]) <等于>
ret = models.Book.objects.exclude(price__in=[66]) <不等于>
ret = models.Book.objects.filter(name__contains='飛') <包含>
ret = models.Book.objects.filter(name__icontains='飛') <不區(qū)分大小寫>
ret = models.Book.objects.filter(sale__range=[50,100]) <范圍>
ret = models.Person.objects.filter(birth__year=1993) <date字段>
類似的還有:startswith,istartswith, endswith, iendswith 

4捐下、ForeignKey操作(Book表中設(shè)置對(duì)Publisher表的外鍵連接)

- 正向查詢

對(duì)象查找(跨表查詢)

語(yǔ)法>>>(對(duì)象.關(guān)聯(lián)字段.字段) 
ret = models.Book.objects.first().publisher
ret = models.Book.objects.first().publisher.id
ret = models.Book.objects.first().publisher.name

字段查找(跨表查詢)

語(yǔ)法>>>(關(guān)聯(lián)字段__字段)
ret = models.Book.objects.values('publisher__id','publisher__name')
ret = models.Book.objects.values_list('publisher__id','publisher__name')
- 反向查詢

對(duì)象查找(跨表查詢)

語(yǔ)法>>>(obj.表名_set)
//在Book表中創(chuàng)建外鍵時(shí)沒(méi)有指定related_name
ret = models.Publisher.objects.get(id = 3).book_set.all()
ret = models.Publisher.objects.filter(id = 3)[0].book_set.all()

//在Book表中創(chuàng)建外鍵時(shí)指定related_name='books'
ret = models.Publisher.objects.get(id = 3).books.all()

字段查找(跨表查詢)

語(yǔ)法>>>(表名__字段)
ret = models.Publisher.objects.values('name','book__name')
ret = models.Publisher.objects.values_list('name','book__name')

5、 ManyToManyField操作(Book表中設(shè)置對(duì)Publisher表的外鍵連接)

- class RelatedManager --->關(guān)聯(lián)管理器

概念:"關(guān)聯(lián)管理器"是在一對(duì)多或者多對(duì)多的關(guān)聯(lián)上下文中使用的管理器萌业。它存在于下面兩種情況:1坷襟、外鍵關(guān)系的反向查詢。 2生年、多對(duì)多關(guān)聯(lián)關(guān)系婴程。簡(jiǎn)單來(lái)說(shuō)就是當(dāng) 點(diǎn)后面的對(duì)象 可能存在多個(gè)的時(shí)候就可以使用以下的方法。

幾種常用的方法:
- create()---->創(chuàng)建一個(gè)新的對(duì)象抱婉,保存對(duì)象档叔,并將它添加到關(guān)聯(lián)對(duì)象集之中,返回新創(chuàng)建的對(duì)象蒸绩。
ret = models.Book.objects.create(name='跟幫政掃黃',price=34,publisher_id=4)
ret = models.Author.objects.first().books.create(name = '追風(fēng)箏的人',publisher_id =1,price = 56)
- add()--->把指定的model對(duì)象添加到關(guān)聯(lián)對(duì)象集中衙四。
添加對(duì)象>>> author_objs = models.Author.objects.filter(id__lt=3)
添加對(duì)象>>> models.Book.objects.first().authors.add(*author_objs)
添加id>>> models.Book.objects.first().authors.add(*[1, 2])
- set()--->更新model對(duì)象的關(guān)聯(lián)對(duì)象。
book_obj = models.Book.objects.first()
book_obj.authors.set([2, 3])
- remove()--->從關(guān)聯(lián)對(duì)象集中移除執(zhí)行的model對(duì)象
book_obj = models.Book.objects.first()
book_obj.authors.remove(3)
- clear()--->從關(guān)聯(lián)對(duì)象集中移除一切對(duì)象患亿。
book_obj = models.Book.objects.first()
book_obj.authors.clear()
重點(diǎn)注意:
- 1传蹈、對(duì)于ForeignKey對(duì)象,clear()和remove()方法僅在null=True時(shí)存在步藕。
- 2惦界、對(duì)于所有類型的關(guān)聯(lián)字段,add()咙冗、create()沾歪、remove()和clear(),set()都會(huì)馬上更新數(shù)據(jù)庫(kù)。換句話說(shuō)雾消,在關(guān)聯(lián)的任何一端灾搏,都不需要再調(diào)用save()方法。

6仪或、聚合查詢和分組查詢

- 聚合查詢

aggregate()是QuerySet 的一個(gè)終止子句确镊,意思是說(shuō),它返回一個(gè)包含一些鍵值對(duì)的字典范删。鍵的名稱是聚合值的標(biāo)識(shí)符蕾域,值是計(jì)算出來(lái)的聚合值。鍵的名稱是按照字段和聚合函數(shù)的名稱自動(dòng)生成出來(lái)的。

用到的內(nèi)置函數(shù):from django.db.models import Avg, Sum, Max, Min, Count
ret = models.Book.objects.aggregate(Sum('price'),Count('id'),Max('price'),Min('price'),average = Avg('price'))
- 分組查詢
  • 統(tǒng)計(jì)每一本書的作者個(gè)數(shù)
ret = models.Book.objects.all().annotate(author_num = Count('author')) for i in ret: print([i.name](http://i.name),i.author_num)
  • 統(tǒng)計(jì)出每個(gè)出版社買的最便宜的書的價(jià)格
方法一:
ret = models.Publisher.objects.all().annotate(cheaper = Min('book__price')).values('name','cheaper')

方法二:
ret = models.Book.objects.values_list('publisher__name').annotate(cheaper = Min('price'))
  • 統(tǒng)計(jì)不止一個(gè)作者的圖書
ret = models.Book.objects.all().annotate(num = Count('author')).filter(num__gt =1)
  • 根據(jù)一本圖書作者數(shù)量的多少對(duì)查詢集 QuerySet進(jìn)行排序
ret = models.Book.objects.all().annotate(num = Count('author')).order_by('-num')

查詢各個(gè)作者出的書的總價(jià)格

ret = models.Author.objects.annotate(sum_price = Sum('books__price')).values_list('name','sum_price')

- F查詢和Q查詢

1.F查詢:

Django 提供 F() 來(lái)做對(duì)兩個(gè)字段的值的比較旨巷。F() 的實(shí)例可以在查詢中引用字段巨缘,來(lái)比較同一個(gè) model 實(shí)例中兩個(gè)不同字段的值。

- 查詢書籍銷量大于庫(kù)存的
ret = models.Book.objects.filter(sale__gt=F('stock')).values('name','sale','stock')
- 將所有書籍的庫(kù)存加50
ret = models.Book.objects.all().update(price = F('stock')+50)
- 延伸到對(duì)char字段的操作-->在所有書名后面加上(第一版)
from django.db.models.functions import Concat
from django.db.models import Value

ret = models.Book.objects.all().update(name = Concat(F('name'),Value('(第一版)')))

2.Q查詢

filter() 等方法中的關(guān)鍵字參數(shù)查詢都是一起進(jìn)行“AND” 的采呐。 如果你需要執(zhí)行更復(fù)雜的查詢(例如OR語(yǔ)句)若锁,你可以使用Q對(duì)象。

- 作者名是王計(jì)飛或劉德凱的書
ret = models.Book.objects.all().filter(Q(author__name='王計(jì)飛')|Q(author__name='劉德凱')).values('name','author__name')
- 比較一下兩者的區(qū)別(一本書的查詢)
ret = models.Book.objects.all().filter(author__name = '王計(jì)飛')

補(bǔ)充:

  • limit_choices_to的作用是設(shè)置篩選條件斧吐,在admin中只顯示篩選后的內(nèi)容又固。

四、Django中的常用代碼段:

1煤率、事務(wù)操作的代碼格式:

import os
if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()
    import datetime
    from app01 import models
     
    try:
        from django.db import transaction
        with transaction.atomic():
            操作內(nèi)容
    except Exception as e:
        print(str(e))

2仰冠、Django終端打印SQL語(yǔ)句

在Django項(xiàng)目的settings.py文件中,在最后復(fù)制粘貼如下代碼:

?LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}?

3蝶糯、在Python腳本中調(diào)用Django環(huán)境:

  import os
if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()
    from app01 import models
    books = models.Book.objects.all()
    print(books)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洋只,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子昼捍,更是在濱河造成了極大的恐慌识虚,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妒茬,死亡現(xiàn)場(chǎng)離奇詭異担锤,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)郊闯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門妻献,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人团赁,你說(shuō)我怎么就攤上這事育拨。” “怎么了欢摄?”我有些...
    開(kāi)封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵熬丧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我怀挠,道長(zhǎng)析蝴,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任绿淋,我火速辦了婚禮闷畸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吞滞。我一直安慰自己佑菩,他們只是感情好盾沫,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著殿漠,像睡著了一般赴精。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绞幌,一...
    開(kāi)封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天蕾哟,我揣著相機(jī)與錄音,去河邊找鬼莲蜘。 笑死谭确,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的菇夸。 我是一名探鬼主播琼富,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼庄新!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起薯鼠,我...
    開(kāi)封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤择诈,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后出皇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體羞芍,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年郊艘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了荷科。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纱注,死狀恐怖畏浆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狞贱,我是刑警寧澤刻获,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站瞎嬉,受9級(jí)特大地震影響蝎毡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜氧枣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一沐兵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧便监,春花似錦扎谎、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)移袍。三九已至,卻和暖如春老充,著一層夾襖步出監(jiān)牢的瞬間葡盗,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工啡浊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留觅够,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓巷嚣,卻偏偏與公主長(zhǎng)得像喘先,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子廷粒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

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

  • 原文:https://my.oschina.net/liuyuantao/blog/751438 查詢集API 參...
    陽(yáng)光小鎮(zhèn)少爺閱讀 3,815評(píng)論 0 8
  • 目錄 models.py文件內(nèi)容如下 以下所有查詢及操作均基于此models.py實(shí)現(xiàn) 一坝茎、 基于對(duì)象的跨表查詢 ...
    CaiGuangyin閱讀 1,160評(píng)論 0 3
  • 模塊間聯(lián)系越多涤姊,其耦合性越強(qiáng),同時(shí)表明其獨(dú)立性越差( 降低耦合性嗤放,可以提高其獨(dú)立性)思喊。軟件設(shè)計(jì)中通常用耦合度和內(nèi)聚...
    riverstation閱讀 2,064評(píng)論 0 8
  • 1 ORM常用操作 1.1 概念 對(duì)象關(guān)系映射(英語(yǔ):Object Relational Mapping,簡(jiǎn)稱OR...
    Spareribs閱讀 648評(píng)論 0 6
  • 青春一晃二十載次酌,年華空逝流水中恨课。 荒唐迷茫至今日,功名未就學(xué)未成岳服。 加冠始慕圣賢道剂公,年長(zhǎng)更覺(jué)要用功。 路途艱難須努...
    道遠(yuǎn)筆記閱讀 179評(píng)論 0 1