Python基础day59Django模型层查询
外键字段的增删改查
# 多对多的外键增删改查 图书和作者是多对多,借助于第三张表实现的,如果想绑定图书和作者的关系,本质上就是在操作第三方表 # 如何操作第三张表 '''问题:让你给图书添加一个作者,他俩的关系是多对多''' # 多对多的增删改查 # 给图书id=2添加一个作者id=1 book_obj = models.Book.objects.filter(pk=2).first() # app01.Author.None:跨越到第三张表 print(book_obj.authors) # 添加信息 book_obj.authors.add(1) # 也可一次性添加多位作者id book_obj.authors.add(2, 3) '''也支持直接写对象''' author_obj1 = models.Author.objects.filter(pk=1).first() author_obj2 = models.Author.objects.filter(pk=2).first() author_obj3 = models.Author.objects.filter(pk=2).first() book_obj.authors.add(author_obj1, author_obj2, author_obj3) '''删除 类似添加,也可以直接写对象''' book_obj.authors.remove(1) book_obj.authors.remove(2, 3) '''修改''' # 这本书的作者id只有1,2,3 book_obj.authors.set([1, 2, 3]) '''清空表 id不重置''' book_obj.authors.clear() ''' 总结 通过字段点 add remove set clear 四个方法 '''
多表查询
子查询和连表查询
子查询:一个SQL语句的执行结果当成另一个SQL语句的执行条件,分步操作 连表查询:把多个表关联在一起拼接成一个大的虚拟表,然后按照单表查询 inner join left join right join union select * from course inner join teacher on course.id=teacher_course_id where id=1; select * from course as c inner join teacher as t on course.id=teacher_course_id left join class on class.id=c.class_id where c.id=1
正反向的概念
# 先判断是正向还是反向查询 正向: 外键字段在我手上,我查你就是正向查询 # 图书查出版社:外键字段在图书表中,正向查询 反向: 外键字段在我手上,你查我就是反向查询 # 出版社查图书,外键字段在图书表中,反向查询 # 判断出来正向和反向之后有什么用 正向查询按照字段查询(外键字段) 反向查询按照表名小写或者表名小写_set
子查询
# 子查询 # 1. 查询书籍主键为1的出版社 # 书籍查出版社----------->正向查询------------>按字段查询 book_obj1 = models.Book.objects.filter(pk=1).first() print(book_obj1.publish.title) # xxx出版社 # 2.查询书籍主键为2的作者 # 书籍查询作者------------>正向查询------------>按字段 book_obj2 = models.Book.objects.filter(pk=2).first() print( book_obj2.authors.all()) # <QuerySet [<Author: Author object>, <Author: Author object>, <Author: Author object>]> print(book_obj2.authors.all()[0]) # Author object print(book_obj2.authors.all()[0].name) # name # 支持循环,将每个结果都循环出来 for i in book_obj2.authors.all(): print(i) # 3. 查询作者ccy的电话号码 # # 作者查作者详情------------->正向查询---------------->按字段查询 author_obj3 = models.Author.objects.filter(name='ccy').first() print(author_obj3.author_detail) # 找到名字对应的作者详情对象 print(author_obj3.author_detail.phone) # 精确找到phone # 4. 查询出版社是常成毅出版社的书 # 出版社查询书籍 - -------------->反向查询 - --------------->按照表名小写或者_set publish_obj4 = models.Publish.objects.filter(title='常成毅出版社').first() print(publish_obj4.book_set) # app01.Book.None xian连接外键 print(publish_obj4.book_set.all()) # 再找到对象 <QuerySet [<Book: Book object>, <Book: Book object>]> print(publish_obj4.book_set.all()[0].title) # 《莫欺少年穷》 print(publish_obj4.book_set.all()[1].title) # 《莫欺老年穷》 # 5. 查询作者是ccy写过的书 # 作者查询书籍------------->反向查询------------>按照表名小写或者_set author_obj5 = models.Author.objects.filter(name='ccy').first() print(author_obj5.book_set.all()[0].title) # 《莫欺中年穷》 # 6.查询手机号是110的作者姓名 # 作者详情查询作者--------------->反向查询------------>按照表名小写或者_set author_detail_object = models.AuthorDetail.objects.filter(phone=110).first() print(author_detail_object.author.name) # ccy ''' 总结: 1. 什么时候加_Set 2. 什么时候.all() 当查询的结果是有多个的时候,就需要以上两个操作 '''
聚合查询(aggregate)
'''sum max min avg count''' # sql: select sum(price) from table group by ''; # 求书籍表中得书的平均价格 select avg(price) from book; from django.db.models import Max, Min, Sum, Avg, Count # 以后在导模块的时候,只要是跟数据库相关的一般都在 django.db django.db.models # res = models.Book.objects.aggregate(Avg('price')) res = models.Book.objects.aggregate(Max('price'), Min('price'), Sum('price'), Avg('price'), Count('id')) print(res)
分组查询(annotate)
# 分组查询:group by # 分组之后只能取到分组的依据,按照什么字段分组就只能取到这个字段的值,前提是严格模式 # 非严格模式就可以取到所有字段的值 # 如何设置严格模式 1. 使用命令修改 查看sql_mode show variables like '%mode%'; @@select sql_mode; # 设置严格模式 set global sql_mode='ONLY_FULL_GROUP_BY' 2. 使用配置文件 # ... 回头要复习的 # 1.统计每一本书的作者个数 # 按照书的id来分组 select * from table group by id res = models.Book.objects.annotate() # annotate这个关键字它就是按照models后面的这个表分组 res = models.Book.objects.annotate(author_num=Count('authors__pk')).values('author_num', 'title') res = models.Book.objects.annotate(author_num=Count('authors')).values('author_num', 'title') print(res) # 2.统计每个出版社卖的最便宜的书的价格 res = models.Publish.objects.annotate(min_price=Min('book__price')).values('min_price', 'name') print(res) # 3.统计不止一个作者的图书 # 先按照图书分组,求出每个图书的作者个数,包括了作者个数为0或者1的等,再次过滤做这个个数大于1的 res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1).values('author_num', 'title','id') print(res) # 4.查询每个作者出的书的总价格 res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('sum_price', 'name') print(res)
F查询
# 1. 查询卖出数大于库存数的书籍 # sql: select * from table where maichu > kucun; '''F查询''' from django.db.models import F # 1. 查询卖出数大于库存数的书籍 res = models.Book.objects.filter(maichu__gt=F('kucun')).all() print(res[0].title) # 2.将所有书籍的价格提升500块 sql: update book set price = price+500 ; res = models.Book.objects.update(price=F('price')+500) # 3.将所有书的名称后面加上爆款两个字 # 如果是更新的字符串不能够这么来写,专业的语法来写 res = models.Book.objects.update(title=F('title')+'爆款') from django.db.models.functions import Concat from django.db.models import Value res = models.Book.objects.update(title=Concat(F('title'), Value('爆款')))
Q查询
# 适用于或者的关系查询 '''Q查询''' from django.db.models import Q # # 1.查询卖出数大于100或者价格小于600的书籍 # select *from table where maichu>100 or price < 600; res = models.Book.objects.filter(maichu__gt=100, price__lt=600).all() # and关系 res = models.Book.objects.filter(Q(maichu__gt=100), Q(price__lt=600)).all() # and关系 <QuerySet []> res = models.Book.objects.filter(Q(maichu__gt=100)| Q(price__lt=600)).all() # OR关系 <QuerySet []> res = models.Book.objects.filter(~Q(maichu__gt=100)| Q(price__lt=600)).all() # OR关系 <QuerySet []> res = models.Book.objects.filter(~Q(maichu__gt=100)| ~Q(price__lt=600)).all() # OR关系 <QuerySet []> res = models.Book.objects.filter(~(Q(maichu__gt=100)| Q(price__lt=600))).all() # OR关系 <QuerySet []> print(res) # Q的高阶用法 q = Q() q.connector = 'or' param = requests.GET.get("param") q.children.append(("maichu__gt", 600)) q.children.append((param +"__gt", 600)) q.children.append(("price__lt", 100)) res = models.Book.objects.filter(q) print(res)
Django中如何开启事务
# 事务的四大特性(ACID) 原子性 隔离性 持久性 一致性 # 事务的隔离级别 # 事务的几个关键 1.开启事务 start transaction; 2. 提交事务 commit; 3. 回滚事务 rollback; # 作用:保证安全,保证多个SQL语句要么同时执行成名, 要么同时失败 '''Django中如何开启事务''' from django.db import transaction try: with transaction.atomic(): # sql1 # sql2 ... models.Book.objects.filter(maichu__gt=100, price__lt=600).update() models.Book.objects.filter(maichu__gt=100, price__lt=600).create() except Exception as e: print(e) transaction.rollback() '''BBS作业里面就可以使用事务'''