查詢數(shù)據(jù)
- 數(shù)據(jù)庫(kù)的查詢需要使用管理器對(duì)象進(jìn)行
- 通過(guò) MyModel.objects 管理器方法調(diào)用查詢接口
方法 說(shuō)明 all() 查詢?nèi)坑涗?返回QuerySet查詢對(duì)象 get() 查詢符合條件的單一記錄 filter() 查詢符合條件的多條記錄 exclude() 查詢符合條件之外的全部記錄 ...
-
all()方法
- 方法: all()
- 用法: MyModel.objects.all()
- 作用: 查詢MyModel實(shí)體中所有的數(shù)據(jù)
- 等同于
- select * from tabel
- 等同于
- 返回值: QuerySet容器對(duì)象,內(nèi)部存放 MyModel 實(shí)例
- 示例:
from bookstore.models import Book books = Book.objects.all() for book in books: print("書名", book.title, '出版社:', book.pub)
-
在模型類中定義
def __str__(self):方法可以自定義默認(rèn)的字符串class Book(models.Model): title = ... def __str__(self): return "書名: %s, 出版社: %s, 定價(jià): %s" % (self.title, self.pub, self.price) -
查詢返回指定列(字典表示)
方法: values('列1', '列2')
用法: MyModel.objects.values(...)
-
作用: 查詢部分列的數(shù)據(jù)并返回
- select 列1,列2 from xxx
-
返回值: QuerySet
- 返回查詢結(jié)果容器,容器內(nèi)存字典,每個(gè)字典代表一條數(shù)據(jù),
- 格式為: {'列1': 值1, '列2': 值2}
-
示例:
from bookstore.models import Book books = Book.objects.values("title", "pub") for book in books: print("書名", book["title"], '出版社:', book['pub']) print("book=", book)
-
查詢返回指定列(元組表示)
方法:values_list('列1','列2')
用法:MyModel.objects.values_list(...)
-
作用:
- 返回元組形式的查詢結(jié)果
-
返回值: QuerySet容器對(duì)象,內(nèi)部存放
元組- 會(huì)將查詢出來(lái)的數(shù)據(jù)封裝到元組中,再封裝到查詢集合QuerySet中
-
示例:
from bookstore.models import Book books = Book.objects.values_list("title", "pub") for book in books: print("書名", book[0], '出版社:', book[1]) print("book=", book) # ('Python', '清華大學(xué)出版社')...
-
排序查詢
方法:order_by
用法:MyModel.objects.order_by('-列','列')
-
作用:
- 與all()方法不同,它會(huì)用SQL 語(yǔ)句的ORDER BY 子句對(duì)查詢結(jié)果進(jìn)行根據(jù)某個(gè)字段選擇性的進(jìn)行排序
說(shuō)明:
默認(rèn)是按照升序排序,降序排序則需要在列前增加'-'表示-
示例:
from bookstore.models import Book books = Book.objects.order_by("price") for book in books: print("書名:", book.title, '定價(jià):', book.price)
-
條件查詢 - filter
方法: filter(條件)
-
語(yǔ)法:
MyModel.objects.filter(屬性1=值1, 屬性2=值2) -
返回值:
- QuerySet容器對(duì)象,內(nèi)部存放 MyModel 實(shí)例
-
說(shuō)明:
- 當(dāng)多個(gè)屬性在一起時(shí)為"與"關(guān)系,即當(dāng)
Books.objects.filter(price=20, pub="清華大學(xué)出版社")返回定價(jià)為20且出版社為"清華大學(xué)出版社"的全部圖書
- 當(dāng)多個(gè)屬性在一起時(shí)為"與"關(guān)系,即當(dāng)
-
示例:
# 查詢書中出版社為"清華大學(xué)出版社"的圖書 from bookstore.models import Book books = Book.objects.filter(pub="清華大學(xué)出版社")
for book in books:
print("書名:", book.title)# 查詢Author實(shí)體中name為王老師并且age是28歲的 authors=Author.objects.filter(name='王老師',age=28) ``` -
條件查詢 - exclude
方法: exclude(條件)
-
語(yǔ)法:
- MyModel.objects.exclude(條件)
-
作用:
- 返回不包含此
條件的 全部的數(shù)據(jù)集
- 返回不包含此
-
示例:
- 查詢
清華大學(xué)出版社,定價(jià)等于50以外的全部圖書
books = Book.objects.exclude(pub="清華大學(xué)出版社", price=50) for book in books: print(book) - 查詢
-
條件查詢 - get
方法: get(條件)
-
語(yǔ)法:
- MyModel.objects.get(條件)
-
作用:
- 返回滿足條件的唯一一條數(shù)據(jù)
-
說(shuō)明:
- 該方法只能返回一條數(shù)據(jù)
- 查詢結(jié)果多余一條數(shù)據(jù)則拋出,Model.MultipleObjectsReturned異常
- 查詢結(jié)果如果沒(méi)有數(shù)據(jù)則拋出Model.DoesNotExist異常
-
示例:
from bookstore.models import Book book = Book.objects.get(id=1) print(book.title)
查詢謂詞
- 每一個(gè)查詢謂詞是一個(gè)獨(dú)立的查詢功能
-
__exact: 等值匹配Author.objects.filter(id__exact=1) # 等同于select * from author where id = 1 -
__contains: 包含指定值Author.objects.filter(name__contains='w') # 等同于 select * from author where name like '%w%' __startswith: 以 XXX 開(kāi)始__endswith: 以 XXX 結(jié)束-
__gt: 大于指定值Author.objects.filer(age__gt=50) # 等同于 select * from author where age > 50 __gte: 大于等于__lt: 小于__lte: 小于等于-
__in: 查找數(shù)據(jù)是否在指定范圍內(nèi)- 示例
Author.objects.filter(country__in=['中國(guó)','日本','韓國(guó)']) # 等同于 select * from author where country in ('中國(guó)','日本','韓國(guó)') -
__range: 查找數(shù)據(jù)是否在指定的區(qū)間范圍內(nèi)# 查找年齡在某一區(qū)間內(nèi)的所有作者 Author.objects.filter(age__range=(35,50)) # 等同于 SELECT ... WHERE Author BETWEEN 35 and 50; 詳細(xì)內(nèi)容參見(jiàn): https://docs.djangoproject.com/en/2.2/ref/models/querysets/#field-lookups
-
示例
MyModel.objects.filter(id__gt=4) # 等同于 SELECT ... WHERE id > 4; -
練習(xí):
查詢Book表中price大于等于50的信息
查詢Author表中姓王的人的信息
查詢Author表中Email中包含"w "的人的信息
修改數(shù)據(jù)
- 修改單個(gè)實(shí)體的某些字段值的步驟:
- 查
- 通過(guò) get() 得到要修改的實(shí)體對(duì)象
- 改
- 通過(guò) 對(duì)象.屬性 的方式修改數(shù)據(jù)
- 保存
- 通過(guò) 對(duì)象.save() 保存數(shù)據(jù)
- 如:
from bookstore.models import Book abook = Book.objects.get(id=10) abook.market_price = "10.5" abook.save()
- 查
- 通過(guò) QuerySet 批量修改 對(duì)應(yīng)的全部字段
直接調(diào)用QuerySet的update(屬性=值) 實(shí)現(xiàn)批量修改
返回值:更新數(shù)據(jù)的數(shù)量
-
如:
# 將id大于3的所有圖書價(jià)格定為0元 books = Book.objects.filter(id__gt=3) books.update(price=0) # 將所有書的零售價(jià)定為100元 books = Book.objects.all() books.update(market_price=100)
刪除數(shù)據(jù)
- 刪除記錄是指刪除數(shù)據(jù)庫(kù)中的一條或多條記錄
- 刪除單個(gè)MyModel對(duì)象或刪除一個(gè)查詢結(jié)果集(QuerySet)中的全部對(duì)象都是調(diào)用 delete()方法
- 刪除單個(gè)對(duì)象
- 步驟
- 查找查詢結(jié)果對(duì)應(yīng)的一個(gè)數(shù)據(jù)對(duì)象
- 調(diào)用這個(gè)數(shù)據(jù)對(duì)象的delete()方法實(shí)現(xiàn)刪除
- 示例:
try: auth = Author.objects.get(id=1) auth.delete() except: print(刪除失敗)
- 步驟
- 刪除查詢結(jié)果集
- 步驟
- 查找查詢結(jié)果集中滿足條件的全部QuerySet查詢集合對(duì)象
- 調(diào)用查詢集合對(duì)象的delete()方法實(shí)現(xiàn)刪除
- 示例:
# 刪除全部作者中,年齡大于65的全部信息 auths = Author.objects.filter(age__gt=65) auths.delete()
- 步驟
聚合查詢
- 聚合查詢是指對(duì)一個(gè)數(shù)據(jù)表中的一個(gè)字段的數(shù)據(jù)進(jìn)行部分或全部進(jìn)行統(tǒng)計(jì)查詢,查bookstore_book數(shù)據(jù)表中的全部書的平均價(jià)格,查詢所有書的總個(gè)數(shù)等,都要使用聚合查詢
-
不帶分組聚合
不帶分組的聚合查詢是指導(dǎo)將全部數(shù)據(jù)進(jìn)行集中統(tǒng)計(jì)查詢
-
聚合函數(shù)【需要導(dǎo)入】:
- 導(dǎo)入方法:
from django.db.models import * - 聚合函數(shù):
- Sum, Avg, Count, Max, Min
- 導(dǎo)入方法:
-
語(yǔ)法:
- MyModel.objects.aggregate(結(jié)果變量名=聚合函數(shù)('列'))
-
返回結(jié)果:
- 由 結(jié)果變量名和值組成的字典
- 格式為:
- `{"結(jié)果變量名": 值}
-
示例:
# 得到所有書的平均價(jià)格 from bookstore.models import Book from django.db.models import Avg result = Book.objects.aggregate(myAvg=Avg('price')) print("平均價(jià)格是:", result['myAvg']) print("result=", result) # {"myAvg": 58.2} # 得到數(shù)據(jù)表里有多少本書 from django.db.models import Count result = Book.objects.aggregate(mycnt=Count('title')) print("數(shù)據(jù)記錄總個(gè)數(shù)是:", result['mycnt'])
print("result=", result) # {"mycnt": 10}
``` -
分組聚合
分組聚合是指通過(guò)計(jì)算查詢結(jié)果中每一個(gè)對(duì)象所關(guān)聯(lián)的對(duì)象集合,從而得出總計(jì)值(也可以是平均值或總和),即為查詢集的每一項(xiàng)生成聚合。
-
語(yǔ)法:
- QuerySet.annotate(結(jié)果變量名=聚合函數(shù)('列'))
-
用法步驟:
-
通過(guò)先用查詢結(jié)果MyModel.objects.values 查找查詢要分組聚合的列
- MyModel.objects.values('列1', '列2')
- 如:
pub_set = Book.objects.values('pub')
print(pub_set) # <QuerySet [{'pub': '清華大學(xué)出版社'}, {'pub': '清華大學(xué)出版社'}, {'pub_hou {'pub': '機(jī)械工業(yè)出版社'}, {'pub': '清華大學(xué)出版社'}]>
``` -
通過(guò)返回結(jié)果的 QuerySet.annotate 方法分組聚合得到分組結(jié)果
- QuerySet.annotate(名=聚合函數(shù)('列'))
- 返回 QuerySet 結(jié)果集,內(nèi)部存儲(chǔ)結(jié)果的字典
- 如:
pub_count_set = pub_set.annotate(myCount=Count('pub')) print(pub_count_set) # <QuerySet [{'pub': '清華大學(xué)出版社', 'myCount': 7}, {'pub': '機(jī)械工業(yè)出版社', 'myCount': 3}]>
-
-
示例:
- 得到哪兒個(gè)出版社共出版多少本書
def test_annotate(request): from django.db.models import Count from . import models # 得到所有出版社的查詢集合QuerySet pub_set = models.Book.objects.values('pub') # 根據(jù)出版社查詢分組,出版社和Count的分組聚合查詢集合 pub_count_set = pub_set.annotate(myCount=Count('pub')) # 返回查詢集合 for item in pub_count_set: print("出版社:", item['pub'], "圖書有:", item['myCount']) return HttpResponse('請(qǐng)查看服務(wù)器端控制臺(tái)獲取結(jié)果')
F對(duì)象
- 一個(gè)F對(duì)象代表數(shù)據(jù)庫(kù)中某條記錄的字段的信息
-
作用:
- 通常是對(duì)數(shù)據(jù)庫(kù)中的字段值在不獲取的情況下進(jìn)行操作
- 用于類屬性(字段)之間的比較。
-
用法
- F對(duì)象在數(shù)據(jù)包 django.db.models 中,使用時(shí)需要先導(dǎo)入
from django.db.models import F
- F對(duì)象在數(shù)據(jù)包 django.db.models 中,使用時(shí)需要先導(dǎo)入
-
語(yǔ)法:
from django.db.models import F F('列名') -
說(shuō)明:
- 一個(gè) F() 對(duì)象代表了一個(gè)model的字段的值
- F對(duì)象通常是對(duì)數(shù)據(jù)庫(kù)中的字段值在不加載到內(nèi)存中的情況下直接在數(shù)據(jù)庫(kù)服務(wù)器端進(jìn)行操作
- 示例1
- 更新Book實(shí)例中所有的零售價(jià)漲10元
Book.objects.all().update(market_price=F('market_price')+10) 'UPDATE `bookstore_book` SET `market_price` = (`bookstore_book`.`market_price` + 10) # 以上做法好于如下代碼 books = Book.objects.all() for book in books: book.market_price=book.marget_price+10 book.save() - 示例2
- 對(duì)數(shù)據(jù)庫(kù)中兩個(gè)字段的值進(jìn)行比較,列出哪兒些書的零售價(jià)高于定價(jià)?
from django.db.models import F from bookstore.models import Book books = Book.objects.filter(market_price__gt=F('price')) 'SELECT * FROM `bookstore_book` WHERE `bookstore_book`.`market_price` > (`bookstore_book`.`price`) for book in books: print(book.title, '定價(jià):', book.price, '現(xiàn)價(jià):', book.market_price)
Q對(duì)象
當(dāng)在獲取查詢結(jié)果集 使用復(fù)雜的邏輯或
|、 邏輯非~等操作時(shí)可以借助于 Q對(duì)象進(jìn)行操作-
如: 想找出定價(jià)低于20元 或 清華大學(xué)出版社的全部書,可以寫成
Book.objects.filter(Q(price__lt=20)|Q(pub="清華大學(xué)出版社")) -
Q對(duì)象在 數(shù)據(jù)包 django.db.models 中。需要先導(dǎo)入再使用
from django.db.models import Q
-
作用
- 在條件中用來(lái)實(shí)現(xiàn)除 and(&) 以外的 or(|) 或 not(~) 操作
-
運(yùn)算符:
- & 與操作
- | 或操作
- ? 非操作
-
語(yǔ)法
from django.db.models import Q Q(條件1)|Q(條件2) # 條件1成立或條件2成立 Q(條件1)&Q(條件2) # 條件1和條件2同時(shí)成立 Q(條件1)&~Q(條件2) # 條件1成立且條件2不成立 ... -
示例
from django.db.models import Q # 查找清華大學(xué)出版社的書或價(jià)格低于50的書 Book.objects.filter(Q(market_price__lt=50) | Q(pub_house='清華大學(xué)出版社')) # 查找不是機(jī)械工業(yè)出版社的書且價(jià)格低于50的書 Book.objects.filter(Q(market_price__lt=50) & ~Q(pub_house='機(jī)械工業(yè)出版社'))
原生的數(shù)據(jù)庫(kù)操作方法
- 使用MyModel.objects.raw()進(jìn)行 數(shù)據(jù)庫(kù)查詢操作查詢
- 在django中,可以使用模型管理器的raw方法來(lái)執(zhí)行select語(yǔ)句進(jìn)行數(shù)據(jù)查詢
-
語(yǔ)法:
MyModel.objects.raw(sql語(yǔ)句,[拼接參數(shù)])
-
用法
MyModel.objects.raw('sql語(yǔ)句', [拼接參數(shù)])
-
返回值:
- RawQuerySet 集合對(duì)象 【只支持基礎(chǔ)操作,比如循環(huán)】
示例
books = Book.objects.raw('select * from bookstore_book')
for book in books:
print(book)
#sql注入問(wèn)題
s1 = Book.objects.raw('select * from bookstore_book where id=%s'%('1 or 1=1'))
s2 = Book.objects.raw('select * from bookstore_book where id=%s',['1 or 1=1'])
- 使用django中的游標(biāo)cursor對(duì)數(shù)據(jù)庫(kù)進(jìn)行 增刪改查 操作
在Django中跨國(guó)模型類直接操作數(shù)據(jù)庫(kù)
-
使用步驟:
- 導(dǎo)入cursor所在的包
- Django中的游標(biāo)cursor定義在 django.db.connection包中,使用前需要先導(dǎo)入
- 如:
from django.db import connection
- 用創(chuàng)建cursor類的構(gòu)造函數(shù)創(chuàng)建cursor對(duì)象,再使用cursor對(duì)象,為保證在出現(xiàn)異常時(shí)能釋放cursor資源,通常使用with語(yǔ)句進(jìn)行創(chuàng)建操作
- 如:
from django.db import connection with connection.cursor() as cur: cur.execute('執(zhí)行SQL語(yǔ)句', '拼接參數(shù)')
- 如:
- 導(dǎo)入cursor所在的包
-
示例
# 用SQL語(yǔ)句將id 為 10的 書的出版社改為 "XXX出版社" from django.db import connection with connection.cursor() as cur: cur.execute('update bookstore_book set pub_house="XXX出版社" where id=10;') with connection.cursor() as cur: # 刪除 id為1的一條記錄 cur.execute('delete from bookstore_book where id=10;')