Django--ORM 多表查询
一 . 建立外键
一对一建立外键
外键名称 = models.OneToOneField(to='要连接的类名', to_field='字段')
一对多建立外键
外键名称 = models.ForeignKey(to='要连接的类名',to_field='字段') # 外键要写在一对多的 那个多的类 下面,比如一个老师对应很多学生,外键就要写在学生的下面
多对多建立外键
外键名称 = models.ManyToManyField(to='另一个类名') # 这个外键名称(属性)要写在其中一个类的下面,然后to=另一个类名, 这个外键就相当于第三张表(多对多建立外键必须通过第三张表)
二 . 多表查询(基于子查询)
# models.py创建表
class Author(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=16)
age = models.IntegerField()
# to后面加类名 to_field后面写类名中的字段名 这是一对一的外键写法
author_detail = models.OneToOneField(to='AuthorDetail', to_field='id')
def __str__(self):
return self.name class AuthorDetail(models.Model):
id = models.AutoField(primary_key=True)
addr = models.CharField(max_length=16)
tel = models.IntegerField() class Publish(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=16)
addr = models.CharField(max_length=16) class Book(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=16)
price = models.DecimalField(max_digits=6,decimal_places=2)
# 在Book上publish变成了publish_id 这是一对多的外键写法
publish = models.ForeignKey(to='Publish',to_field='id')
# 这个authors不是字段,他只是Book类里面的一个属性 这是多对多的建立第三张表的写法
authors = models.ManyToManyField(to='Author')
对authors(第三张表的操作)
# 给id=1的书籍添加id=5和id=6这两个作者
book_obj = models.Book.objects.filter(id=1)[0]
book_obj.authors.add(*[5, 6]) # 数字的类型是int或者str都行 # 把id=1的书籍的作者全部删掉
book_obj = models.Book.objects.filter(id=1)[0]
book_obj.authors.clear() # 把id=1的书籍中的id=5和id=6的这两个作者删掉
book_obj = models.Book.objects.filter(id=1)[0]
book_obj.authors.remove(*[5, 6]) # 把id=1的书籍中的作者名更新成id=7和id=8这两个作者
book_obj = models.Book.objects.filter(id=1)[0]
book_obj.authors.set([7, 8])
# set 不能用*[7, 8] set的执行流程是先把作者全部删除,然后添加[7, 8]
一对一正向查询(外键在哪个表,他找别人就是正向)
# 萧峰的住址
author_obj = models.Author.objects.get(name='萧峰')
# author_obj.外键名.要查字段
print(author_obj.author_detail.addr) # author_detail = models.OneToOneField(to='AuthorDetail', to_field='id')
# 这个author_detail就是外键名
一对一反向查询(没有外键的表查询有外键的表就是反向查询)
# 地址是大理的英雄名字
author_detail_obj = models.AuthorDetail.objects.get(addr='大理')
# author_detail_obj.要查询的表名(要小写).要查字段
print(author_detail_obj.author.name)
一对多正向查询
# 出版天龙八部的出版社名字
book_obj = models.Book.objects.get(name='天龙八部')
# book_obj.外键名.要查字段
print(book_obj.publish.name)
一对多反向查询
# 查询城市是西夏的出版社 出版的图书
pub_obj = models.Publish.objects.get(city='西夏')
# pub_obj.表名_set.all().values('name') 因为不止一个所以需要 表名_set
print(pub_obj.book_set.all().values('name'))
多对多正向查询
# 天龙八部的作者都有谁
book_obj = models.Book.objects.get(name='天龙八部')
# book_obj.第三张表的属性.all().values(字段)
print(book_obj.authors.all().values('name')) # 这个authors虽然在Book类下面,但是它不是字段,只是属性.
多对多反向查询
# 令狐冲写了哪些书
author_obj = models.Author.objects.get(name='令狐冲')
# author_obj.表名_all().values(字段)
print(author_obj.book_set.all().values('name'))
三 .基于双下划线跨表查询(基于join)
正向查询按照外键名,反向查询按照表名(小写), 和上面的一样,外键字段在哪个表中, 他找别人就是正向,相反就是反向查询
# 一对一查询
# 查询萧峰作者的电话号
# 正向查询 按照外键 "__" 这个是双下划线
# models.类名(表名).objects.filter(条件).values(外键名__字段)
ret = models.Author.objects.filter(name='萧峰').values('author_detail__tel') # 反向查询 按照类名(小写)
# models.类名.objects.filter(另一个类名(小写)__条件).values(字段)
ret = models.AuthorDetail.objects.filter(book__name='萧峰').values('tel')
# 一对多查询
# 金庸出版社出版过的所有书籍的名字
# 正向查询 按照外键
# models.类名.objects.filter(外键名__条件).values(字段)
ret = models.Book.objects.filter(publish__name='金庸出版社').values('name') # 反向查询 按照类名(小写)
# models.类名.objects.filter(条件).values(另一个类名(小写)__字段)
ret = models.Publish.objects.filter(name='金庸出版社').values('book__name')
# 多对多查询
# 萧峰这个作者写了哪几本书
# 正向查询 按照外键
# models.类名.objects.filter(外键__条件).values(字段)
ret = models.Book.objects.filter(authors__name='萧峰').values('name') # 反向查询 按照类名
# models.类名.objects.filter(条件).values(另一个类名__字段)
ret = models.Author.objects.filter(name='萧峰').values('book__name')
# 连续跨表查询
# 查询金庸出版社出版的所有的书名及作者名
# 正向查询
ret = models.Book.objects.filter(publish__name='金庸出版社').values('name','authors__name') # 反向查询
ret = models.Publish.objects.filter(name='金庸出版社').values('book__name','book__authors__name')
# 由于Author和Publish两个表没有外键关系所以需要通过Book表找到作者名 # 电话以6开头的作者出版过的书名及出版社名
# 正向查询
ret = models.Book.objects.filter(authors__author_detail__tel__startswith='').values('name','publish__name') # 反向查询
# 方法一
ret = models.Publish.objects.filter(book__authors__author_detail__tel__startswith='').values('name','book__name') # 方法二
ret = models.AuthorDetail.objects.filter(tel__startswith='').values('author__book__name','author__book__publish__name')
# 由于Author与Book是多对多的关系,并且authors写在Book下面,所以通过author往回找的时候直接author__book.
四 . 聚合查询, 分组查询, F查询, Q查询
聚合查询
# aggregate(*args, **kwargs) 是queryset的终结,queryset对象后面.aggregate 得到一个字典不再是queryset对象
# 计算所有书的平均价格
from django.db.models import Avg
models.Book.objects.all().aggregate(Avg('price')) # 也可以给它起名字 aggregate(a = Avg('price'))
# 这个objects后面的 all()写不写都行 可以直接在控制器(models.Book.objects)后面写 # 还可以不止生成一个聚合函数
from django.db.models import Avg,Max,Min
models.Book.objects.aggregate(Avg('price'),Max('price'),Min('price'))
分组查询
------------------单表查询(用上边的Book表)----------------------
# 查询每个出版社出版了多少本书 annotate里面写聚合函数(Max,Min,Avg,Count) 得到一个queryset对象 models.Book.objects.values('publish').annotate(c=Count('id'))
# values里面写的是要分组的字段,每个出版社意思就是以出版社为分组, annotate里面写你要统计的, 而且必须是 别名=聚合函数这个格式 ------------------多表查询(用之前那些表) --------------------- 查询每个出版社出版了多少本书
models.Publish.objects.values('name').annotate(c=Count('book__id'))
# 下面这个方法比较常用
models.Publish.objects.annotate(c=Count('book__id')).values('name','c')
# 如果用上边的那个方法出现关于group by的错误的话,需要进行一下操作:
进入mysql里执行SELECT @@GLOBAL.sql_mode; 看看里面是否有
ONLY_FULL_GROUP_BY参数,如果有的话需要到配置文件中(my.ini或者是mysql.cnf)修改
sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'
然后重启mysql.
F查询(可以进行两个字段的比较)
# 比如说在Book表里面加上评论数comment_num 和点赞数support_num
# 查询评论数大于点赞数的书
from django.db.models import F
models.Book.objects.filter(comment_num__gt=F('support_num')) # django 还支持F()对象之间以及F()对象与常数之间的加减乘除
models.Book.objects.filter(comment_num__gt=F('support_num')*2) # 也可以用F()来进行修改
# 把每本书的价格添加1000
models.Book.objects.update(price=F('price')+1000)
Q查询
像filter()中的条件一起查询的时候都是and, 如果想要有or的关系就需要用到Q查询
Q对象可以使用$(and) |(or) ~(not) 操作组合起来. 当一个操作符用在两个Q对象上面时,这两个Q对象由于操作符的作用就变成了一个新的对象.
# 查询作者名字为萧峰或者段誉出版的书
models.Book.objects.filter(Q(authors__name='萧峰')|Q(authors__name='段誉')) # 可以组合其他的操作符进行操作
# 查询作者是萧峰或者是段誉价格不高于100的书
models.Book.objects.filter(Q(author__name='萧峰')|Q(author__name='段誉')& ~Q(price__gt=100)) # 如果有关键字参数和Q查询同时在筛选条件里面,Q查询必须要写到关键字参数前面
# 查询作者名字是萧峰或者是段誉的价格为100 的书
models.Book.objects.filter(Q(author__name='萧峰')|Q(author__name='段誉'),price=100)
# 这个关键字参数要写到Q查询的后面,中间用逗号隔开,表示and的意思
五 . python脚本中调用Django环境(django外部脚本使用models)
import os if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
import django
django.setup() from app01 import models #引入也要写在上面三句之后 books = models.Book.objects.all()
print(books)
Django--ORM 多表查询的更多相关文章
- Django ORM多表查询练习
ORM多表查询 创建表结构: from django.db import models # 创建表结构 # Create your models here. class Class_grade(mod ...
- django ORM 连表查询2
set() 更新model对象的关联对象 book_obj=models.Book.objects.first() book_obj.authors.set([2,3]) 把book_obj这个对象重 ...
- Django ORM多表查询
基于双下划线查询 根据存的时候,字段的数据格式衍生的查询方法 1.年龄大于35岁 res = models.AuthorDetails.objects.filter(age__lt=80) print ...
- django ORM 连表查询
db_index=True 如果设置该字段就可以设置索引 auto_now_add 代表设置创建时候的时间 auto_now 每次更新数据记录时会更新该字段 to_field 设置要关联表的字 ...
- Django ORM单表查询必会13条
必知必会13条 操作下面的操作之前,我们实现创建好了数据表,这里主要演示下面的操作,不再细讲创建准备过程 <1> all(): 查询所有结果 <2> filter(**kwar ...
- django orm跨表查询废话最少最精简版
在model.py中: class B1(models.Model): u1= models.CharField(max_length=32) #多 class B2(models.Model): f ...
- python 之 Django框架(orm单表查询、orm多表查询、聚合查询、分组查询、F查询、 Q查询、事务、Django ORM执行原生SQL)
12.329 orm单表查询 import os if __name__ == '__main__': # 指定当前py脚本需要加载的Django项目配置信息 os.environ.setdefaul ...
- 第五章、Django之多表查询进阶与事务
目录 第五章.Django之多表查询 一.聚合查询 二.分组查询 三.F与Q查询 四.查询优化 五.Django开启事务 六.自定义char字段 七.ORM常用字段 第五章.Django之多表查询 一 ...
- 第十七篇 ORM跨表查询和分组查询---二次剖析
ORM跨表查询和分组查询---二次剖析 阅读目录(Content) 创建表(建立模型) 基于对象的跨表查询 一对多查询(Publish与Book) 多对多查询 (Author 与 Book) 一对一查 ...
- ORM单表查询,跨表查询,分组查询
ORM单表查询,跨表查询,分组查询 单表查询之下划线 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值models ...
随机推荐
- [matlab] 20.图与网络 matlab自带函数使用
matlab自带的biography(产生一个句柄) 可以用于画图 R=[1 1 2 4 1 2 3 3 5 7 3 4 5 6 7 8]; % 起始节点编号 C=[2 3 3 3 4 5 5 6 6 ...
- Python框架学习之Flask中的常用扩展包
Flask框架是一个扩展性非常强的框架,所以导致它有非常多的扩展包.这些扩展包的功能都很强大.本节主要汇总一些常用的扩展包. 一. Flask-Script pip install flask-scr ...
- binarySearch(int[] a,int fromIndex,int toIndex, int key)的用法
package com.Summer_0420.cn; import java.util.Arrays; /** * @author Summer * binarySearch(int[] a,int ...
- JavaScript模块化思想requireJS的使用
1. 使用require.js的意义 (1)实现JS文件的异步加载,避免网页因为加载JS文件缓慢造成网页未响应 (2)管理模块之间的依赖性,便于代码的编写和维护.页面中只需要引入require.j ...
- pycharm 安装和首次使用
由于本人也是开发语言的学习小白,所以对于开发时使用的工具也不算太熟悉,不过这里还是要推荐一下本人使用过 的两款工具: 1.pycharm :2.eclipse 这是我用的比较顺手的两个工具当然这两个 ...
- 【开源】微信小程序、小游戏以及 Web 通用 Canvas 渲染引擎 - Cax
Cax 小程序.小游戏以及 Web 通用 Canvas 渲染引擎 Github → https://github.com/dntzhang/cax 点我看看 DEMO 小程序 DEMO 正在审核中敬请 ...
- POST BOY : Restful API 调试工具
在使用asp.net webapi开发中,一般情况下会使用一些工具来模拟请求. 其中有一款chrome浏览器插件POST MAN比较不错. 但是由于国内google服务使用不稳定,所以我自己写了一个简 ...
- LeetCode 961. N-Repeated Element in Size 2N Array
In a array A of size 2N, there are N+1 unique elements, and exactly one of these elements is repeate ...
- Log4J.xml配置详解
原文地址:https://blog.csdn.net/genyizha/article/details/74502812 Appender Appender:日志输出器,配置日志的输出级别.输出位置等 ...
- codeforces#1090 D. New Year and the Permutation Concatenation(打表找规律)
题意:给出一个n,生成n的所有全排列,将他们按顺序前后拼接在一起组成一个新的序列,问有多少个长度为n的连续的子序列和为(n+1)*n/2 题解:由于只有一个输入,第一感觉就是打表找规律,虽然表打出来了 ...