# 查询库存大于销量的书籍# res = models.Book.objects.filter(stock_amount > sale_amount) 语法错误# res = models.Book.objects.filter(stock_amount__getsale_amount) 语法错误
当查询条件的左右两边的数据都需要表中的数据时建议使用F查询
from django.db.models import F
res = models.Book.objects.filter(stock_amount__gt=F('sale_amount'))
print(res) # <QuerySet [<Book: 美洲地理-图书对象>, <Book: 欧洲探索-图书对象>, # <Book: 太平洋记录-图书对象>, <Book: 大西洋记录-图书对象>, <Book: 初中英语-图书对象>]># 将所有书的价格提升9块
res = models.Book.objects.update(book_price=F('book_price') + 9)
print(res) # 9# 将所有书的名称后面加上‘-即将售罄’后缀
res = models.Book.objects.update(book_title=F('book_title') + '-即将售罄') # 慎用,会清空书名字段# 修改char字段的正确操作from django.db.models.functions import Concat, ConcatPair
from django.db.models import Value
res = models.Book.objects.update(book_title=Concat(F('book_title'), Value('-即将售罄')))
print(res) # 9
res = models.Book.objects.update(book_title=ConcatPair(F('book_title'), Value('-即将售罄')))
print(res) # 9
Q查询
# 查询价格大于30或者卖出大于2500的书籍
res = models.Book.objects.filter(book_price__gt=30,sale_amount__gt=2500)
print(res) # <QuerySet [<Book: 大学物理-图书对象>, <Book: 大学化学-图书对象>]>print(res.query) # SELECT `app01_book`.`id`, `app01_book`.`book_title`, # `app01_book`.`book_price`, `app01_book`.`publish_time`, `app01_book`.`publish_id`, # `app01_book`.`stock_amount`, `app01_book`.`sale_amount` FROM `app01_book` # WHERE (`app01_book`.`book_price` > 30 AND `app01_book`.`sale_amount` > 2500)
结论:filter括号内多个条件默认是and关系
from django.db.models import Q
'''使用Q对象可以支持逻辑运算符'''
res = models.Book.objects.filter(Q(book_price__gt=30), Q(sale_amount__gt=2500)) # 逗号是and关系print(res) # <QuerySet [<Book: 大学物理-图书对象>, <Book: 大学化学-图书对象>]>print(res.query) # SELECT `app01_book`.`id`, `app01_book`.`book_title`, `app01_book`.`book_price`, `app01_book`.`publish_time`, `app01_book`.`publish_id`, `app01_book`.`stock_amount`, `app01_book`.`sale_amount` FROM `app01_book` WHERE (`app01_book`.`book_price` > 30 AND `app01_book`.`sale_amount` > 2500)
res = models.Book.objects.filter(Q(book_price__gt=30) | Q(sale_amount__gt=2500)) # 管道符是or关系print(res) # <QuerySet [<Book: 中国地理-图书对象>, <Book: 亚洲地理-图书对象>, <Book: 美洲地理-图书对象>, <Book: 欧洲探索-图书对象>, <Book: 太平洋记录-图书对象>, <Book: 初中英语-图书对象>, <Book: 大学物理-图书对象>, <Book: 大学化学-图书对象>]>print(res.query) # SELECT `app01_book`.`id`, `app01_book`.`book_title`, `app01_book`.`book_price`, `app01_book`.`publish_time`, `app01_book`.`publish_id`, `app01_book`.`stock_amount`, `app01_book`.`sale_amount` FROM `app01_book` WHERE (`app01_book`.`book_price` > 30 OR `app01_book`.`sale_amount` > 2500)
res = models.Book.objects.filter(~Q(book_price__gt=30)) # ~是not操作print(res) # <QuerySet [<Book: 大西洋记录-图书对象>]>print(res.query) # SELECT `# Q对象进阶用法filter(price=40)
filter('price'=40)
当我们需要编写一个搜索功能,条件是由用户指定, 这种情况左边的数据就是一个字符串
q_obj = Q()
q_obj.connector = 'or'# 默认是and,可改为or
q_obj.children.append(('book_price__gt', 70))
q_obj.children.append(('sale_amount__gt', 3000))
res = models.Book.objects.filter(q_obj)
print(res) # <QuerySet [<Book: 太平洋记录-图书对象>, <Book: 大学物理-图书对象>, <Book: 大学化学-图书对象>]>print(res.query) # SELECT `app01_book`.`id`, `app01_book`.`book_title`, `app01_book`.`book_price`, `app01_book`.`publish_time`, `app01_book`.`publish_id`, `app01_book`.`stock_amount`, `app01_book`.`sale_amount` FROM `app01_book` WHERE (`app01_book`.`book_price` > 70 or `app01_book`.`sale_amount` > 3000)
ORM查询优化
数据库管理,应当尽量减少与数据库的交互
# ORM查询默认都是惰性查询
只编写ORM语句并不会直接执行SQL语句,只有后续的代码用到了前面的ORM语句才会执行
# ORM查询默认自带分页功能# only与defer
res = models.Book.objects.values('book_title', 'book_price')
'''需求:单个结果还是以对象的形式展示,可以直接通过句点符操作'''for i in res:
print(i.get('book_title'))
res = models.Book.objects.only('book_title', 'book_price')
for obj in res:
print(obj.book_title)
print(obj.book_price)
print(obj.publish_time)
注意:only会产生对象结果集,对象点括号内出现的字段不会再走数据库查询
但是如果点击括号内没有的字段也可以获取到数据,但每次执行SQL语句
res = models.Book.objects.defer('book_title', 'book_price')
for obj in res:
print(obj.book_title)
print(obj.book_price)
print(obj.publish_time)
注意:defer与only刚好相反,对象点括号内出现的字段会走数据库查询
如果点括号内没有的字段也可获取到数据,而且不会每次执行SQL语句
# select_related和prefetch_related
res = models.Book.objects.select_related('publish')
for obj in res:
print(obj.book_title)
print(obj.publish.press_name)
print(obj.publish.press_addr)
注意:select_related括号内只能传‘一对一’和‘一对多’字段,不能传‘多对多’字段
效果是内部直接连接表(inner join),然后将连接之后的大表中所有的数据全部封装到数据对象中
后续对象通过正反向查询跨表,内部不会再执行SQL语句
res = models.Book.objects.prefetch_related('publish')
for obj in res:
print(obj.book_title)
print(obj.publish.press_name)
print(obj.publish.press_addr)
注意:将多次查询之后的结果封装到数据对象中,后续对象通过正反向查询跨表时内部不会再执行SQL语句
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?