一、準(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)