外键字段的增删改查
多对多的外键增删改查
图书和作者是多对多,借助于第三张表实现的,如果想绑定图书和作者的关系,本质上就是在操作第三方表
操作第三张表
问题:让你给图书添加一个作者,他俩的关系可是多对多
让你给图书id=2添加一个作者id=1
add方法
book_obj = models.Book.objects.filter(pk=2).first() print(book_obj.book_author) # app01.Publish.None这句话代表已经跨到book_publish这张表 # add方法就可以给第三张表添加作者id book_obj.book_author.add(1) # 还可以一次添加多个作者 book_obj.book_author.add(2,3) # 也支持对象添加,把作者对象查出来 author_obj1 = models.Author.objects.filter(pk=4).first() author_obj2 = models.Author.objects.filter(pk=5).first() book_obj.book_author.add(author_obj2,author_obj1)
删除图书id=2且作者id=3的作者、
remove方法
book_obj = models.Book.objects.filter(pk=2).first() print(book_obj.book_author) # app01.Publish.None这句话代表已经跨到book_publish这张表 book_obj.book_author.remove(3) #也可以一次删除多个 book_obj.book_author.remove(4, 5)
也可以使用author对象删除
修改
set方法
book_obj = models.Book.objects.filter(pk=2).first() print(book_obj.book_author) book_obj.book_author.set([3, 4]) # 修改必须使用可变类型数据
清空表的方法
clear方法
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.book_author)
book_obj.book_author.clear()
总结:通过字典点 外键字段
add remove set clear # 四个方法
多表查询
子查询和连表查询
子查询:一个SQL语句的执行结果当成另一个SQL语句的执行条件,分步操作
连表查询:把多个表关联在一起拼接成一个大的虚拟表,然后按照单表查询
链接方法:inner join、left join、right join
原生SQL代码
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的出版社
书籍查出版社----------->正向查询------------>按字段查询
res = models.Book.objects.filter(pk=1).first() print(res.publish.publish_name) # 北京出版社
2.查询书籍主键为2的作者 书籍查询作者------------>正向查询------------>按字段
res = models.Book.objects.filter(pk=2).first() print(res.book_author.all()) print(res.book_author.all()[0].author_name) print(res.book_author.all()[1].author_name)
3.查询作者jack的电话号码
作者查作者详情------------->正向查询---------------->按字段查询
res = models.Author.objects.filter(author_name='老林').first() print(res.author_detail.author_phone)
4.查询出版社是北京出版社出版的书
出版社查询书籍--------------->反向查询---------------->按照表名小写或者_set
res=models.Publish.objects.filter(publish_name='北京出版社').first() print(res.book_set.all()) print(res.book_set.all()[0].book_name)
5.查询作者是jack写过的书
作者查询书籍------------->反向查询------------>按照表名小写或者_set
res=models.Author.objects.filter(author_name='老徐').first() print(res.book_set.all()) print(res.book_set.all()[0].book_name)
6.查询手机号是110的作者姓名
作者详细查询作者--------------->反向查询------------>按照表名小写或者_set
res=models.AuthorDetail.objects.filter(author_phone=110).first() print(res.author.author_name)
总结:当查询的结果可以是多个的时候就加_set和all()
多表查询之连表查询(基于双下划线的查询)
1.查询jerry的手机号和作者姓名
作者查询作者详情----------->正向查询------------>按字段
res=models.Author.objects.filter(author_name='老张').values('author_detail__author_phone','author_name') print(res) print(res[0].get('author_detail__author_phone')) print(res[0].get('author_name'))
作者详情查询作者信息------------->反向----------------->表名小写
res = models.AuthorDetail.objects.filter(author__author_name='老张').values('author_phone', 'author__author_name') print(res[0].get('author_phone')) print(res[0].get('author__author_name'))
2.查询书籍主键为1的出版社名称和书的名称
书籍查出版社------------------>正向查询------------>按字段
res = models.Book.objects.filter(pk=1).values('publish__publish_name','publish__book__book_name') print(res[0].get('publish__publish_name')) print(res[0].get('publish__book__book_name'))
书籍查出版社------------------>反向----------------->表名小写
res1=models.Publish.objects.filter(book__pk=1).values('book__book_name','publish_name') print(res1[0].get('book__book_name')) print(res1[0].get('publish_name'))
3.查询书籍主键为1的作者姓名
书籍查询作者------------->正向查询------------>按字段
res=models.Book.objects.filter(pk=1).values('book_author__author_name','book_name') print(res[0].get('book_author__author_name')) print(res[0].get('book_name'))
书籍查询作者------------->反向----------------->表名小写
res1=models.Author.objects.filter(book__pk=1).values('author_name','book__book_name') print(res1[0].get('author_name')) print(res1[0].get('book__book_name'))
查询书籍主键是1的作者的手机号
res = models.Book.objects.filter(pk=1).values('book_author__author_detail__author_phone', 'book_name', 'book_author__author_name') print(res[0].get('book_author__author_detail__author_phone')) print(res[0].get('book_name')) print(res[0].get('book_author__author_name'))
聚合查询(aggregate)
聚合函数:sum max min avg count
原生SQL语句:
求表格价格 select sum(price) from book # 求书籍表中得书的平均价格 select avg(price) from book;
以后在导模块的时候,只要是跟数据库相关的一般都在
django.db
django.db.models
Django中
from django.db.models import Sum,Max,Avg,Count,Min RES=models.Book.objects.aggregate(Sum('book_prince'),Avg('book_prince'),Count('book_prince'),Max('book_prince')) print(RES)
分组查询annotate
mysql中分组:group by
分组之后只能取到分组的依据,按照什么字段分组就只能取到这个字段的值,前提是严格模式
如何设置严格模式
1. 使用命令修改
查看sql_mode
show variables like '%mode%';
@@select sql_mode;
设置严格模式
set global sql_mode='ONLY_FULL_GROUP_BY'
2.在配置文件中修改
1.统计每一本书的作者个数
res = models.Book.objects.annotate(author_count=Count('book_author__pk')).values('author_count', 'book_name') print(res)
通过外键字段来查询
res = models.Book.objects.annotate(author_count=Count('book_author')).values('author_count', 'book_name')
print(res)
2.统计每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(publish_min=Min('book__book_prince')).values('publish_min', 'book__book_name') print(res)
3.统计不止一个作者的图书
res=models.Book.objects.annotate(book_count=Count('book_author__pk')).filter(book_count__gt=1).values('book_count','book_name','id') print(res) 列表套字典
4.查询每个作者出的书的总价格
res = models.Author.objects.annotate(price_sum=Sum('book__book_prince')).values('author_name', 'book__book_name', 'price_sum') print(res)
F与Q查询
F查询
from django.db.models import F 1. 查询卖出数大于库存数的书籍 sql: select * from table where maichu > kucun; 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查询
适用于或者的关系查询
from django.db.models import Q 1.查询卖出数大于100或者价格小于600的书籍 SQL语句: 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作业里面就可以使用事务'
标签:__,多表,author,models,res,改查,查询,book From: https://www.cnblogs.com/shanghaipudong/p/17604407.html