镇江网站建设个,网站蜘蛛爬行,网站 错位,个人网站 虚拟主机价格目录
一.多表查询引入
1.数据准备
2.外键的增删改查
#xff08;1#xff09;一对多外键的增删改查
1.1外键的增加
1.2外键的删除
1.3外键的修改
(2)多对多外键的增删改查
2.1增加
2.2删除
2.3更改
2.4清空
3.正反向概念
二.多表查询
1.子查询#xff08;基于…目录
一.多表查询引入
1.数据准备
2.外键的增删改查
1一对多外键的增删改查
1.1外键的增加
1.2外键的删除
1.3外键的修改
(2)多对多外键的增删改查
2.1增加
2.2删除
2.3更改
2.4清空
3.正反向概念
二.多表查询
1.子查询基于对象的跨表查询
2.联表查询基于双下划线的跨表查询
三.聚合查询
四.分组查询
五.F与Q查询
1.F查询
2.Q查询 一.多表查询引入
1.数据准备
class Book(models.Model):title models.CharField(max_length32)price models.DecimalField(max_digits8, decimal_places2)publish_date models.DateField(auto_now_addTrue)# 一对多publish models.ForeignKey(toPublish)# 多对多authors models.ManyToManyField(toAuthor)class Publish(models.Model):name models.CharField(max_length32)addr models.CharField(max_length64)# 该字段不是给models看的而是给校验行组件使用的email models.EmailField()class Author(models.Model):name models.CharField(max_length32)age models.IntegerField()# 一对一author_detail models.OneToOneField(toAuthDetail)class AuthDetail(models.Model):phone models.BigIntegerField()addr models.CharField(max_length40)重载数据库
python36 manage.py makemigrationspython36 manage.py migrate2.外键的增删改查
1一对多外键的增删改查
1.1外键的增加
# 1一对多的外键的增删改查
# 1.1外键的增加 - 直接写实际字段
models.Book.objects.create(title三国演义,price1369.25,publish_id1)# (1.2)外键的增加 - 虚拟字段
publish_obj models.Publish.object.objects.filter(pk2).first()
models.Book.objects.create(title红楼梦,price1569.25,publishpublish_obj)
1.2外键的删除
# (2)一对多的外键删除
models.Publish.objects.filter(pk1).delete()1.3外键的修改
# (2)一对多的外键的修改
# - 直接写实际字段
models.Book.object.filter(pk1).update(publish_id2)
# - 虚拟字段
publish_obj models.publish.objects.filter(pk1).first()models.Book.objects.filter(pk1).update(publishpublish_obj)
(2)多对多外键的增删改查 多对多 增删改查就是在操作第三张表 2.1增加
# 多对多外键的增删改查 - 就是在操作第三张表
# 1如何给书籍添加作者
book_obj models.Book.objects.filter(pk1).first()
# book_obj.authors - 这样我们就已经能操作第三张关系表了
# 书籍ID为1的书籍绑定了一个主键为1的作者
book_obj.authors.add(1)
# 可以传多个参数
book_obj.authors.add(2,3)
# 支持参数传对象 - 且支持多个对象
book_obj.authors.add(author_obj)
2.2删除 支持多个参数/支持对象 # (2)删除
book_obj models.Book.objects.filter(pk1).first()
# 支持多个参数 - 支持多个对象
book_obj.authors.remove(2)
2.3更改 先删除后增加 # 3修改
book_obj models.Book.objects.filter(pk1).first()
# 括号内必须给一个可迭代对象
# 把1删掉替换成2
book_obj.author.set([1,2])
# 把原来都删掉替换成3
book_obj.authors.set([3])
# 支持放对象
book_obj.authors.set([author_obj])
2.4清空
# 4清空
# 在第三张表中清除某一本书和作者的绑定关系
book_obj models.Book.objects.filter(pk1).first()
# 不要加任何参数
book_obj.authors.clear()
3.正反向概念
正向 外键字段在我手上那么我查你就是正向book外键字段在book这边正向出版社反向 外键字段不在我手上那么我查你就是反向出版社外键字段在书这边反向book一对一和一对多的判断也是这样 正向查询按字段 反向查询按表名小写 二.多表查询
1.子查询基于对象的跨表查询
# [1] 基于对象的跨表查询
# (1)查询书籍主键为1的出版社
book_obj models.Book.objects.filter(pk1).first()
# 书查出版社 - 正向 - 按字段查
res book_obj.publish
print(res) # Publish object
print(res.name) # 东方出版社
print(res.addr) # 东方# 2查询书籍主键为2的作者
book_obj models.Book.objects.filter(pk1).first()
# 书查作者 - 正向查询按字段
res book_obj.authors
print(res) # app01.Author.None
# 列表中存放的是作者对象
print(res.all()) # QuerySet [Author: Author object]# 3查询作者 的 电话号码
author_obj models.Author.objects.filter(namedream).first()
# 作者查询作者详情 - 正向查询按字段
res author_obj.author_detail
print(res) # AuthDetail object
print(res.phone) # 110
print(res.addr) # 山东在书写ORM语句的时候跟写SQL语句一样的不要企图一次性将ORM语句写完如果比较复杂需要写一些看一些正向 什么时候需要加 .all()当查询返回的结果是多个的时候就需要用 .all()当查询的结果只有一个的时候就不需要加# 4查询出版社是东方出版社出版的书
# 先拿到出版社对象
publish_obj models.Publish.objects.filter(name东方出版社).first()
# 出版社查书 - 主键字段在书 - 反向查询
res publish_obj.book_set.all()
# publish_obj.book_set
# print(res) # app01.Book.None
# publish_obj.book_set.all()
print(res) # QuerySet [Book: Book object, Book: Book object, Book: Book object]# 5查询作者是dream写过的书
# 先拿到作者对象
author_obj models.Author.objects.filter(namedream).first()
# 作者查书 - 主键在书 - 反向
res author_obj.book_set.all()
print(res) # QuerySet [Book: Book object]# 5查询手机号是 110的作者姓名
# 先拿到作者详情的对象
author_detail_obj models.AuthDetail.objects.filter(phone110).first()
# 详情查作者 - 主键在作者 - 反向
res author_detail_obj.author
print(res) # Author object
print(res.name) # dream基于对象 - 反向查询什么时候需要加 _set.all()查询结果是多个的时候需要加查询结果是多个的时候需要加补充_set.all()反向查询 查询结果是多个的时候需要加 2.联表查询基于双下划线的跨表查询
# [2] 基于双下划线的跨表查询
# 1查询dream的手机号和作者的姓名
# 正向先查询到作者信息再 .value(需要查询信息的表__需要查询的字段,其他字段)
res models.Author.objects.filter(namedream).values(author_detail__phone, name)
print(res) # QuerySet [{author_detail__phone: 110, name: dream}]
# 反向先拿到详情再用作者详情关联作者表通过 __字段的方法 过滤出我们想要的指定数据
res models.AuthDetail.objects.filter(author__namedream).values(phone, author__name)
# AuthDetail.objects.filter(author__namedream)
print(res) # QuerySet [AuthDetail: AuthDetail object]
# AuthDetail.objects.filter(author__namedream).values(phone,author__name)
print(res) # QuerySet [{phone: 110, author__name: dream}]# 2查询书籍主键ID为1的出版社名字和书的名字
# 正向先过滤出书籍ID为1的书籍对象再去关联出版者表利用__字段取值
res models.Book.objects.filter(pk1).values(title, publish__name)
print(res) # QuerySet [{title: 三国演义, publish__name: 东方出版社}]
# 反向先查询到指定出版社再从出版社反向找到书籍名字
res models.Publish.objects.filter(book__id1).values(name, book__title)
print(res) # QuerySet [{name: 东方出版社, book__title: 三国演义}]# 3查询书籍主键ID为1的作者姓名
# 先拿到 书籍主键ID为1的对象再关联作者信息表通过__字段取值
res models.Book.objects.filter(pk1).values(authors__name)
print(res) # QuerySet [{authors__name: dream}]
# 反向 : 先拿到 书籍ID为1的作者数据再去取作者的名字
res models.Author.objects.filter(book__id1).values(name)
print(res) # QuerySet [{name: dream}]# 查询书籍主键是1的作者的手机号
# book author authordetail
res models.Book.objects.filter(pk1).values(authors__author_detail__phone)
print(res) # QuerySet [{authors__author_detail__phone: 110}]只要掌握了正反向的概念以及双下划线查询就可以无限跨表三.聚合查询 # 聚合查询# 聚合查询通常情况下都是配合分组一起使用的只要是和数据库相关的模块基本上都在 django.db.models 里面如果这里面没有 那大概率可能在 django.db 里面from django.db.models import Max, Min, Sum, Count, Avg# 1所有书的平均价格# 正常情况下我们是需要 先进行分组再进行 聚合函数运算的# 但是Django给我们提供了一种方法 aggregate 可以不分组进行某个字段的聚合函数res models.Book.objects.aggregate(Avg(price))print(res) # {price__avg: 1890.083333}# 2一次性使用res models.Book.objects.aggregate(Avg(price), Max(price), Min(price), Sum(price), Count(pk))print(res) # {price__avg: 1890.083333, price__max: Decimal(5959.25), price__min: Decimal(555.25), price__sum: Decimal(11340.50), pk__count: 6}四.分组查询
# 分组查询
MySQL中的分组查询分组之后只能获取到分组的依据组内其他字段都无法获取严格模式中可以修改# 1统计每一本书的作者个数
# models 后面跟的是什么就是按什么分组
# res models.Book.objects.annotate()
#
#
# author_number 是我们自己定义的字段用来存储统计出来的每本书的作者个数
#
# res models.Book.objects.annotate(author_numberCount(authors)).values(title,author_number)
# # 等价于
# # res models.Book.objects.annotate(author_numberCount(authors__pk)).values(title,author_number)
# print(res) # QuerySet [{title: 三国演义, author_number: 1}, {title: 红楼梦, author_number: 0}, {title: 水浒传, author_number: 0}, {title: 论语, author_number: 0}, {title: 孙子兵法, author_number: 0}, {title: 镇魂街, author_number: 0}]# 2统计每个出版社最便宜的书的价格
# res models.Publish.objects.annotate(min_priceMin(book__price)).values(name, min_price)
# print(res) # QuerySet [{name: 东方出版社, min_price: Decimal(555.25)}, {name: 北方出版社, min_price: Decimal(888.25)}]# 3统计不止一个作者的图书
# 3.1先按照图书分组
# 3.2过滤出不止一个作者的图书
# 我的数据有限我统计的是大于 0 的作者的图书
# res models.Book.objects.annotate(author_numCount(authors)).filter(author_num__gt0).values(title,
#
# 只要ORM语句得到的是 一个 queryset 对象
# 那么就可以继续无限制的调用封装 的方法
# author_num)
# print(res) # QuerySet [{title: 三国演义, author_num: 1}]# 4查询每个作者出的书的总价格
res models.Author.objects.annotate(sum_priceSum(book__price)).values(name, sum_price)
print(res) # QuerySet [{name: dream, sum_price: Decimal(1369.25)}, {name: hope, sum_price: None}, {name: sad, sum_price: None}]如果想按照指定的字段分组该如何处理# 如果 annotate 前面没东西 则会按照 Book 分组 如果前面有参数 就会按照前面的参数进行分组 pricemodels.Book.objects.values(price).annotate()五.F与Q查询
1.F查询
# F与Q查询from django.db.models import F, Q# 1查出卖出数大于库存数的书籍
# F 查询 : 帮助我们直接获取到表中的某个字段对应的数据
res models.Book.objects.filter(sales__gtF(stock))
print(res) # QuerySet [Book: 水浒传]# (2) 将所有书籍的价格提升 50
res models.Book.objects.update(priceF(price) 500)
print(res) # 6 - 影响到了 6 条数据# 3将所有书的名称后边加上 爆款两个字
# 在操作字符串的时候F查询不能够直接坐到字符串的拼接
from django.db.models.functions import Concat
from django.db.models import Valueres models.Book.objects.update(titleConcat(F(title), Value(爆款)))
print(res) # 6 - 影响到了 6 条数据2.Q查询
# F与Q查询from django.db.models import F, Q# 1查询卖出数大于100或者价格小于500的书籍# 1.1直接使用 filter 查询数据逗号隔开,里面放的参数是 and 关系
res models.Book.objects.filter(sales__gt100, price__lt500)
print(res) # QuerySet []# 1.2直接使用 Q 查询数据逗号隔开,里面放的参数还是 and 关系
res models.Book.objects.filter(Q(sales__gt100), Q(price__lt500))
print(res) # QuerySet []# 1.3直接使用 Q 查询数据逗号可以换成其他连接符达到效果
res models.Book.objects.filter(Q(sales__gt100) or Q(price__lt500))
# 二者等价 | 或关系 ~ 取反 not 关系
res models.Book.objects.filter(Q(sales__gt100) | Q(price__lt500))
print(res) # QuerySet [Book: 三国演义爆款, Book: 水浒传爆款, Book: 论语爆款, Book: 孙子兵法爆款]# 2 Q的高阶用法 能够将查询条件的左边也变成 字符串形式
# 产生 Q 对象
q Q()
# 修改Q查询的默认连接条件
q.connector or
q.children.append(sales, 100)
q.children.append(stock, 600)
# filter 参数支持Q对象默认还是 and 关系
res models.Book.objects.filter(q)