Django 多表、跨表、聚合、分组查询
前期准备:
创建表
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_time = models.DateField(auto_now_add=True) #该字段新增数据会自动添加实时时间 #出版社 一对多 外键字段建在多的一方
publish = models.ForeignKey(to='Publish')
#作者 多对多 外键字段推荐建在查询频率较高的表
authors = models.ManyToManyField(to='Author') class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64) class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField() #作者详情 一对一 外键字段推荐建在查询频率较高的表
author_detail = models.OneToOneField(to='AuthorDetail') class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=32)
Django多表查询
外键字段的增删改查
外键字段在1.X版本中默认就是级联更新级联删除
2.X版本中则需要手动指定(百度)
一对多 publish
增:
# 增 方式1 直接写实际的表字段 publish_id
models.Book.objects.create(title='三国',price='123.12',publish_id=2)
# 增 方式2
publish_obj = models.Publish.objects.get(pk=1)
models.Book.objects.create(title='水浒传',price=66,publish=publish_obj)
改:
# 改 方式1
models.Book.objects.filter(pk=1).update(publish_id=3)
# 改 方式2
publish_obj = models.Publish.objects.get(pk=4)
models.Book.objects.filter(pk=1).update(publish=publish_obj)
多对多
add:
#1.给书籍和作者绑定关系 add """
add专门给第三张关系表添加数据
括号内即可以传数字也可以传对象 并且都支持传多个
""" book_obj = models.Book.objects.filter(pk=1).first()
# 书籍和作者的关系是由第三张表决定 也就意味着你需要操作第三张表
# 书籍对象点虚拟字段authors就类似于已经跨到书籍和作者的第三张关系表中
# print(book_obj.authors) #app01.Author.None # 方式一
book_obj.authors.add(1) #给书籍绑定一个主键为1的作者
book_obj.authors.add(2,3) # 方式二
author_obj = models.Author.objects.get(pk=2)
author_obj1 = models.Author.objects.get(pk=3)
book_obj.authors.add(author_obj)
book_obj.authors.add(author_obj,author_obj1)
remove:
# 2.移除书籍与作者的绑定关系 remove """
remove专门给第三张关系表移除数据
括号内即可以传数字也可以传对象 并且都支持传多个
""" book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.remove(2)
book_obj.authors.remove(1,3) # author_obj = models.Author.objects.get(pk=2)
# author_obj1 = models.Author.objects.get(pk=3)
# book_obj.authors.remove(author_obj)
# book_obj.authors.remove(author_obj,author_obj1)
set:
# 3 修改书籍与作者的关系 set """
set 修改书籍与作者的关系
括号内支持传数字和对象 但是需要是可迭代对象
""" book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.set((3,))
book_obj.authors.set((2, 3)) author_obj = models.Author.objects.get(pk=2)
author_obj1 = models.Author.objects.get(pk=3)
book_obj.authors.set((author_obj,))
book_obj.authors.set([author_obj,author_obj1])
clear:
# 4 清空书籍与作者关系 """
clear() 清空关系
不需要任何的参数
""" book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear() # 去第三张表中清空书籍为1的所有数据
Django 跨表查询
跨表查询的方式
1.子查询 将一张表的查询结果当做另外一张表的查询条件
2.链表查询
建议:在写sql语句或者orm语句的时候,千万不要想着一次性将语句写完,一定要写一点查一点
正反向的概念
正向
跨表查询的时候,看外键字段是否在当前数据对象中,如果在的话,查询另外一张关系表 叫正向
反向
如果不在叫反向
口诀
正向查询按外键字段
反向查询按表名小写 看情况加_set
基于对象的跨表查询(子查询)
#正向: # 1.查询书籍pk为1的出版社名称
book_obj = models.Book.objects.filter(pk=1).first() #先拿到书籍对象
print(book_obj.publish) #书籍对象点外键字段拿到的是出版社对象
print(book_obj.publish.name)
print(book_obj.publish.addr) # 2.查询书籍pk为2的所有作者的姓名
book_obj = models.Book.objects.filter(pk=2).first()
# print(book_obj.authors) # app01.Author.None
print(book_obj.authors.all()) #<QuerySet [<Author: Author object>]>
author_list = book_obj.authors.all()
for author_obj in author_list:
print(author_obj.name) # 3.查询作者hank的电话号码
author_obj = models.Author.objects.filter(name='hank').first()
print(author_obj.author_detail)
print(author_obj.author_detail.phone) """
正向查询的时候 当外键字段对应的数据可以有多个的时候需要加.all()
否则点外键字段即可获取到对应的数据对象
""" #反向# 4.查询出版社名称为东方出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set) #app01.Book.None
print(publish_obj.book_set.all()) #<QuerySet [<Book: Book object>]> # 5.查询作者hank写过的书
author_obj = models.Author.objects.filter(name='hank').first()
print(author_obj.book_set) # app01.Book.None
print(author_obj.book_set.all()) # 6.查询手机号为120的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
print(author_detail_obj.author.name) """
基于对象的反向查询 表名小写是否需要加_set.all()?
一对多和多对多的时候需要加
一对一不需要
"""
基于双下划线跨表查询(链表查询)
注意:只要表之间有关系,你就可以通过正向的外键字段或者反向的表名小写,连续跨表操作
# 1.查询书籍pk为1的出版社名称
# 正向
res = models.Book.objects.filter(pk=1).values('publish__name') # 写外键字段 就意味着你已经在外键字段管理的那张表中
print(res) #<QuerySet [{'publish__name': '西方出版社'}]>
# 反向
res = models.Publish.objects.filter(book__pk=1).first() # 拿出版过pk为1的书籍对应的出版社
print(res.name) #西方出版社 # 2.查询书籍pk为1的作者姓名和年龄
# 正向
res = models.Book.objects.filter(pk=1).values('title','authors__name','authors__age')
print(res)
# 反向
# res = models.Author.objects.filter(book__pk=1) # 拿出出版过书籍pk为1的作者
res = models.Author.objects.filter(book__pk=1).values('name','age')
print(res) # 3.查询作者是hank的年龄和手机号
# 正向
res = models.Author.objects.filter(name='hank').values('age','author_detail__phone')
print(res)
# 反向
# res = models.AuthorDetail.objects.filter(author__name='hank') #拿到hank的个人详情
res = models.AuthorDetail.objects.filter(author__name='hank').values('phone','author__age')
print(res) # 4.查询书籍pk为的1的作者的手机号
# 正向
res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
print(res) #<QuerySet [{'authors__author_detail__phone': 120}]>
# 反向
res = models.AuthorDetail.objects.filter(author__book__pk=1).values('phone')
print(res) #<QuerySet [{'phone': 120}]>
聚合查询
关键字:aggregate
from django.db.models import Max,Min,Avg,Count,Sum
# 查询所有书的平均价格
res = models.Book.objects.aggregate(Avg('price'))
print(res) # 查询价格最贵的书
res = models.Book.objects.aggregate(Max('price'))
print(res) #查询书的总数
res = models.Book.objects.aggregate(Count("pk"))
print(res) # 查询所有书的总价
res = models.Book.objects.aggregate(Sum('price'))
print(res)
分组查询
关键字:annotate
'''
models后面点什么表名,后面如果直接跟annotate,那就是按照表名分组
''' # 1.统计每一本书的作者个数
res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
print(res) # 2.统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price','book__title')
print(res) # 3.统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title')
print(res) # 4.查询各个作者出的书的总价格
res = models.Author.objects.annotate(price_sum=Sum('book__price')).values('name','price_sum')
print(res) #如何按照表中的某一个指定字段分组
"""
res = models.Book.objects.values('price').annotate() 就是以价格分组
"""
Django 多表、跨表、聚合、分组查询的更多相关文章
- Django day08 多表操作 (五) 聚合,分组查询 和 F,Q查询
一:聚合,分组查询 二:F, Q查询
- Django【第7篇】:Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)
django之跨表查询及添加记录 一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many); ...
- day056-58 django多表增加和查询基于对象和基于双下划线的多表查询聚合 分组查询 自定义标签过滤器 外部调用django环境 事务和锁
一.多表的创建 from django.db import models # Create your models here. class Author(models.Model): id = mod ...
- django中的跨表查询梳理
1.前言 最近在写一个小项目,里面主要涉及的就是表与表之间复杂的关系.当真正开发起来的时候,才发现自己对复杂的表关系间的查询有点混乱,趁着这几天的时间,重新梳理了一下. 2.概念 在开始之前,先明确几 ...
- Django中的跨表查询,多表查询。
一:Django中的ORM进行操作. 必须掌握的十三条: <1> all(): 查询所有结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 & ...
- Django之ORM跨表操作
Django之ORM表查询及添加记录 一.创建表 - 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-man ...
- Django聚合分组查询、常用字段
首先回顾sql中聚合和分组的概念: 如果没有分组,会把整张表作为一个大组,查询字段必须是聚合结果:如果有分组,分组之后,必须要使用聚合的结果作为having的条件. 聚合查询 聚合:aggregate ...
- day67 ORM模型之高阶用法整理,聚合,分组查询以及F和Q用法,附练习题整理
归纳总结的笔记: day67 ORM 特殊的语法 一个简单的语法 --翻译成--> SQL语句 语法: 1. 操作数据库表 创建表.删除表.修改表 2. 操作数据库行 增.删.改.查 怎么连数据 ...
- day058 聚合 分组查询 自定义标签过滤器 外部调用django环境 事务和锁
1.聚合(aggregate) 聚合的主要语法: from django.db.models import Avg , Max , Min , Count models.类名 .objects.all ...
- Django - 一对多跨表操作
1.views.py 2.host.html 运行结果: 通过外键,来进行多表取值(多表取值包括后台取值及前端获取): 多表获取数据时,可以通过以下几种方式实现: 1.从query set 中获取某 ...
随机推荐
- 洛谷 1602 Sramoc问题
Description 话说员工们整理好了筷子之后,就准备将快餐送出了,但是一看订单,都傻眼了:订单上没有留电话号码,只写了一个sramoc(k,m)函数,这什么东西?什么意思?于是餐厅找来了资深顾问 ...
- 在 Linux 安装 IIS?
在 Linuxe 安装 IIS? 在群里有人说他的老大让他在 Linux 中安装 IIS. 一群人回复不同的解决方案. 在 Linux 安装虚拟机,再安装 Windows. (哈哈哈) 这个问题虽然有 ...
- 创建JAVASCRIPT对象3种方法
创建JAVASCRIPT对象3种方法 方法一:直接定义并创建对象实例 var obj = new Object(); //创建对象实例 //添加属性obj.num = 5; //添加属性 o ...
- spring+mybatis 整合
项目目录: 一.导入pom.xml依赖 最下边有 二.在applicationContext.xml配置连接器和数据库的数据源 三.流程:用户请求数据,springmvc解析url,通过控制器和适配器 ...
- Python--day68--ORM内容回顾
Django项目如何使用ORM连接MySQL: 多对多关系讲解:
- servicemix 实例 -- 参考open source ESBs in action这本书
1. 项目结构 2. bean服务处理单元 1)Person类 package esb.chapter3; import java.io.StringWriter; import javax.xml. ...
- 【u224】传送机
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 刷完牙洗完脸,黄黄同学就要上课去了.可是黄黄同学每次去上课时总喜欢把校园里面的每条路都走一遍,当然,黄 ...
- React---钩子函数
钩子函数的状态有4个阶段: <p>1.初始化阶段 (componentWillMount() || componentDidMount()) </p> ...
- java 递归(Recursion)
现在要求输出一个给定目录中的全部文件的路径. 本程序肯定只能依靠递归的操作完成,因为在一个给定的路径下有可能还是文件夹,那么如果是文件夹的话则肯定要继续列出,重复判断. 递归:程序调用自身的编程技巧 ...
- javascript中的offsetWidth、clientWidth、innerWidth及相关属性方法
* offsetWidth 水平方向 width + 左右padding + 左右border-width * offsetHeight 垂直方向 height + 上下padding + 上下bor ...