Django --- ORM表查询
使用数据库之前的配置工作
settings.py中的配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day53',
'USER':'root',
'PASSWORD':'123qwe',
'HOST':'127.0.0.1',
'PORT':3306,
'CHARSET':'utf8'
}}
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
init.py中的配置
import pymysql
pymysql.install_as_MySQLdb()
test.py中配置
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
import django
django.setup()
from app01 import models # 一定要写在下边
单表操作常用的方法
创建数据
# 1.create方法创建数据
book_obj = models.Books.objects.create(title='三国演义',price=123.23,publish_date='2019-11-11')
# 2.利用对象的绑定方法
book_obj = models.Books(title='西游记',price=666.66,publish_date='2000-1-21')
book_obj.save()
修改数据
# 方式1 利用queryset方法
models.Books.objects.filter(pk=1).update(price=444.66)
# 方式2 利用对象
book_obj = models.Books.objects.get(pk=1)
book_obj.price = 222.66
book_obj.save()
# pk会自动帮你找到当前的主键字段,所以会经常使用pk来指代主键字段;
filter查询
filter查询出来的结果是一个Queryset对象
1.只要是queryset对象就可以无限制的调用queryset的方法
2.只要是queryset对象就可以点query查看当前结果内部对应的sql语句
get和filter的区别
1.filter获取到的是一个queryset对象,类似于一个列表
2.get获取到的直接就是数据对象本身
3.当条件不存在的时候,filter直接返回一个空,而get会直接报错,所以推荐使用filter
删除数据
# 1.利用queryset方法 delete()
models.Books.objects.filter(pk=3).delete()
# 2,对象方法
book_obj = models.Books.objects.get(pk=3)
book_obj.delete()
查数据13条
1.查所有 all()
res = models.Books.objects.all() # 返回结果Queryset对象,是列表套对象的行式
2.筛选 filter()
res = models.Books.objects.filter(pk=1,title='三') # 支持多个参数,并且是and关系,不能模糊刷选
3.筛选 get()
res = models.Books.objects.get(title='西游记') # 获取的是数据对象本身,条件不存在的时候会直接报错,并且查询条件必须是唯一
4.取queryset中第一个数据对象 first()
res = models.Books.objects.filter(title='西游记').first()
5.取queryset中最后一个对象 last()
res = models.Books.objects.filter(title='西游记').last()
6.统计数据的个数 count()
num = models.Books.objects.count() # 不需要传入参数
7.获取数据对象中指定的字段的值 values()
res = models.Books.objects.values('title','price')
# 可以有多个,格式是列表套字典
8.获取数据对象中指定的字段的值 values_list()
res = models.Books.objects.values_list('title','price')
# 可以有多个,格式是列表套元组 <QuerySet [('西游记',), ('水浒传',), ('红楼梦',)]>
9.按照指定的字段排序 order_by()
res = models.Books.objects.order_by('price')
res1 = models.Books.objects.all().order_by('price')
# 默认是升序,两者等价,下边的语义更明确
#倒序
res1 = models.Books.objects.all().order_by('-price')
10.颠倒顺序 reverse()
res3 = models.Books.objects.all().order_by('price').reverse()
# 前提是颠倒的对象必须有顺序,(提前排序之后才能颠倒)
11.排除对象 exclude()
res = models.Books.objects.all().exclude(title='三国演义')
# <QuerySet [<Books: 红楼梦>, <Books: 西游记1>, <Books: 西游记2>]>
12.判断查询结果是否有值 exists()
res = models.Books.objects.filter(pk=1).exists()
# 返回时布尔值,但是数据本身就带有布尔值,所以一般不需要使用
13.对查询结果进行去重操作 distinct()
res = models.Books.objects.values('title','price').distinct()
# 去重的前提时数据必须时完全一样的情况下才能够去重,容易忽略的时主键
神奇的下划线方法
查询价格大于X的值
res = models.Books.objects.filter(price__gt=500)
查询价格小于X的值
res = models.Books.objects.filter(price__lt=400)
查询价格大于等于X的值
res = models.Books.objects.filter(price__gte=500)
# 使用数字是小数的时候会查询不到等于的情况
查询小于等于X的值
res = models.Books.objects.filter(price__lte=500)
查询自定义区间内的值
res = models.Books.objects.filter(price__in=[222,444,500])
查询在某区间内的值
res = models.Books.objects.filter(price__range=(200,800)) # 顾头顾尾
查询出版日期是某年的值
res = models.Books.objects.filter(publish_date__year='2019')
查询出版日期是1月份的值
res = models.Books.objects.filter(publish_date__month='1')
# 只按照月份筛选,对年份没有要求
查询是以什么开头的值
res = models.Books.objects.filter(title__startswith='三')
查询是以什么结尾的值
res = models.Books.objects.filter(title__endswith='1')
查询值包含某个字段的值
res = models.Books.objects.filter(title__contains='p') # 默认区分大小写
res = models.Books.objects.filter(title__icontains='p') # 忽略大小写 加i
一对多字段的增删改查
增
# 第一种
models.Book.objects.create(title='三国演义',price=222.33,publish_id=1)
# 第二种
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj)
改
# 第一种
models.Book.objects.filter(pk=1).update(publish_id=2)
# 第二种
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)
删
models.Publish.objects.filter(pk=1).delete() # 默认就是级联删除 级联更新
多对多字段数据的增删改查
增
# 给一本书添加作者
# 第一种
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.author.add(5) # 添加一个
book_obj.author.add(3,5) # 添加多个
# 第二种
author_obj = models.Author.objects.filter(pk=1).first()
book_obj.author.add(author_obj)
#总结
add方法:能够朝第三张表中添加数据,支持添加数据也支持添加对象,
改
# 更改一本书的作者
# 第一种
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.author.set((1,3)) # 必须是可迭代对象
# 第二种
book_obj = models.Book.objects.filter(pk=2).first()
author_obj = models.Author.objects.filter(pk=1).first()
book_obj.author.set((author_obj,)) # 不许是可迭代对象
#总结
set方法:set方法既可以按照数字进行设置,也可以按照对象进行设置,可以传入多个值,但是传入的参数必须是可迭代对象。
删
# 删除书的作者
# 第一种方法
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.remove(1,2)
# 第二种方法
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.remove(author_obj,author_obj1)
#总结
remove方法:可以删除一个,也可以删除多个,并且不需要迭代,
清空
删除某个数据在第三张表中的所有数据
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.author.clear()
# clear清空所有的相关记录,括号内不需要传递参数
跨表查询
注意:关系字段在谁那里,由谁查谁就是正向,如果没有关系字段,就是反向查询
基于对象跨表查询——正向查询
正向查询按字段,反向查询按表名小写+_set
# 查询书id为2的书的出版社名
# 第一种 --- 正向查询
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish)
# 第二种 --- 上下划线查询
publish_obj = models.Publish.objects.filter(book__pk=2).first()
print(publish_obj.publish_name)
基于双下划线跨表查询
正向查询按字段,反向查询按表名小写+_set
# 查询作者'wang'写了哪些书
author_obj = models.Author.objects.filter(username='wang').first()
print(author_obj.book_set.all())
正向查询的时候,根据已有的主键,通过对象.主键的方式可以进入外键所在的表中,此时形成的是外键所在表的对象,根据对象.属性来进行查询需要的内容
authorbook
'__':__使用的时候是基于外键所在的表为查询对象,查询条件为 "表名小写__pk=2" 数字为需要查询的内容的id号,可以通过 " __ " 来使用外键所在的id,使用"__" 的前提是两张表之间使用外键进行关联过。不能没有外键关联使用这种方法
" 表名小写_set ":用book与author的表为例,author与book两张表的键在book中,所以查数对应的作者很简单,但是查作者对应的数就没有办法通过键来进行查询,此时使用 "book_set" 就相当于在author中使用了连接键。
一对一反向查询的时候直接对象.有外键的表名小写,可以进行查询,不需要使用_set方法
什么时候添加.all()
当查询出来的结果为多个的时候使用 .all() 来进行接收,会有提示的报错 app01.Author.None
聚合函数
什么是聚合查询
使用聚合函数进行查询,常用的聚合函数有:Max,Min,Sum,Count,Avg
聚合函数的使用
from django.db.models import Max,Min,Sum,Count,Avg
# 使用的时候是通过 aggregate()
# 使用方法一:直接在同一张表种使用聚合函数
res = models.Book.objects.aggregate(mr = Max('price'))
print(res) # {'mr': Decimal('400.00')}
# 使用方法二:在多表中使用聚合函数
res = models.Publish.objects.filter(pk=1).first().book_set.all().aggregate(ma = Max('price'))
print(res) # {'ma': Decimal('300.00')}
# 使用方法三:直接使用聚合函数
res = models.Book.objects.aggregate(Avg('price'))
print(res) # {'price__avg': 275.0}
# 注意点:
# 1.在同一张表中进行查询的时候,直接使用对象.aggregate的方法来使用,取出来的值是一个对象
# 2.当需要在多表中进行查询的时候,需要先找到对应表的对象,然后通过对象.aggregate的方式来使用
# 3.使用aggregate的时候,括号内只写聚合函数也可以
分组查询
分组查询就是先将需要查询的条件进行分类,然后再会分组后的数据进行条件查询,annotate中表示已经对需要分组的数据分组完成了,并且返回了一张总表,values中是需要对这张表进行查询到的数据,如果,该查询字段没有再分组的表中,会报错。
# 查询各个作者出的书的总价格,作者名字,
res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('username','sum_price')
# 原生SQL语句
SELECT `app01_author`.`username`, SUM(`app01_book`.`price`) AS `sum_price` FROM `app01_author` LEFT OUTER JOIN `app01_book_author` ON (`app01_author`.`id` = `app01_book_author`.`author_id`) LEFT OUTER JOIN `app01_book` ON (`app01_book_author`.`book_id` = `app01_book`.`id`) GROUP BY `app01_author`.`id` ORDER BY NULL
# 打印结果
print(res)
<QuerySet [{'username': 'wang', 'sum_price': Decimal('400.00')}, {'username': 'zhang', 'sum_price': Decimal('500.00')}, {'username': 'qqq', 'sum_price': None}]>
总结:
1.需要查谁就对谁进行分组,“对每一个###”查询,就使用 “ ###” 进行分组,然后再将需要查询的值进行返回,values中的值必须是两张表中有的才能查询出来,没有的会报错。
2.按照先找到对应的表,然后进行分组,再将需要的数据进行查询。
3.分组之后只能拿分组的依据,如果想拿其他的值,只能通过聚合函数来操作,因为数据库中会有严格模式,不让进行查询。
F与Q查询
F查询
F可以通过拿到某个字段中的对应的值来当作筛选条件,
作用场景:在同一行操作总需要根据一个数据对另一个数据进行操作,例如:全体添加字段,查询卖出数大于库存数的商品
例1
**例2 ** 可以对查询出来的值进行加减乘乘除
from django.db.models import F
# 将所有书的价格上涨100块
models.Book.objects.all().update(price=F('price') + 100)
例3 对书名添加内容,需要借助Concat和Value模块
from django.db.models.functions import Concat
from django.db.models import Value
from django.db.models import F
res = models.Book.objects.update(book_name=Concat(F('book_name'),Value('促销')))
总结:F查询可以直接通过 F() 的方式将需要的值取出,而不需要使用对象 . filter() 的方式将值取出,这样的好处是可以对同一行中的数据进行比较处理。
Q查询
使用filter查询的时候提供的是一种 A 和 B 的查询方式,而 Q 是提供一种 A 或 B 的查询方式,既可以包括A,也可以包括B,
Q的高级用法
总结:Q查询查询的是或的关系,可以在多个包含的情况下使用,比filter的使用范围广一些。而对于Q的高级用法,可以将输入的字符串进行查找,不用再使用变量进行查找,可以在用户输入查询的时候使用。
Django --- ORM表查询的更多相关文章
- Django orm进阶查询(聚合、分组、F查询、Q查询)、常见字段、查询优化及事务操作
Django orm进阶查询(聚合.分组.F查询.Q查询).常见字段.查询优化及事务操作 聚合查询 记住用到关键字aggregate然后还有几个常用的聚合函数就好了 from django.db.mo ...
- Django多表查询
一.前言 1.什么是ORM? ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候, ...
- Python - Django - ORM 分组查询补充
单表查询: models.py: from django.db import models class Employee(models.Model): name = models.CharField( ...
- Django orm 常用查询筛选总结
本文主要列举一下django orm中的常用查询的筛选方法: 大于.大于等于 小于.小于等于 in like is null / is not null 不等于/不包含于 其他模糊查询 model: ...
- Django 多表查询
多表查询是模型层的重要功能之一, Django提供了一套基于关联字段独特的解决方案. ForeignKey 来自Django官方文档的模型示例: from django.db import model ...
- django orm 的查询条件
Django的ORM查询操作: 查询数据库操作是一个非常重要的技术.在Django中,查询一般就是使用filter.exclude.get三个方法来实现,在调用这些方法的时候传递不同的查询条件来实现复 ...
- Django单表查询及其方法
单表查询 前期准备 首先新建一个test的python文件,然后再manage.py中导入main语句及其下面的复制到新文件中 并导入django 写上django.setup() 就可以导入对应的m ...
- Django 多表查询练习题 Q查询 F查询 聚合 分组
-------------------------------------------------自己偷的懒,或许用加倍时间也补不回来,珍惜现在的拥有的时光,把我现在! 上节回顾 基于对象的跨表查询( ...
- django 多表查询并返回结果
(不喜勿喷,个人记录) 问题,有两张关联的表,表B的api_id关联表A的id 我想在页面上返回两张表查询之后的共同结果? 因为两张表的id是一样的,就先获取到表A的对象,然后拿表A的对象id当做表B ...
随机推荐
- liunx mysql数据库目录迁移
1.查看mysql安装目录 从目录etc/my.cnf中查看安装目录 2.进入mysql目录,停止mysql服务 命令: cd usr/local/mysql 命令:service mysql sto ...
- Mybatis @Many注解一对多关联映射
@Many注解:fetchType属性用于配置是否延迟加载
- [洛谷P5367]【模板】康托展开
题目大意:给定一个$n$的排列,求它在$n$的全排列中的名次 题解:康托展开,对于一个全排列,第$i$为有$n+1-i$种选择,用变进制数表示,这一位就是$n+1-i$进制.记排列中第$[1,i)$中 ...
- activiti串行会签的使用
1.串行任务的配置 2.当任务走到串行会签节点时,会从你之前保存的流程变量中找集合(我这里设置的assigneeList),串行会签会根据这个集合设置一系列该节点的流程变量 3.结束条件的设置,若满足 ...
- cesium 检测视图改变的代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- Java调用Http/Https接口(1)--编写服务端
Http接口输入的数据一般是键值对或json数据,返回的一般是json数据.本系列文章主要介绍Java调用Http接口的各种方法,本文主要介绍服务端的编写,方便后续文章里的客户端的调用.文中所使用到的 ...
- jquery实现输入框实时统计字数和设置字数限制功能
<html> <header> <meta charset="utf-8"> <title>测试实时字数显示</title&g ...
- Math对象的一些方法
ceil(n) 返回n向上取整的最近的整数floor(n) 返回n向下取整到最近的整数max(a,b,c...) 返回最大值min(a,b,c...) 返回最小值round(n) 返回n四舍五入的最近 ...
- PHP 常用数据库操作
1.建立与数据库服务器的连接(前提数据库服务器必须打开) 第一个参数:本地地址 第二个参数:数据库账户 第三个参数:数据库密码 第四个参数:数据库名称 $connection = mysqli_con ...
- 微信小程序分享小程序码的生成,多参数以及参数的获取
如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 官方文档地址:https://developers.weixin.qq.com/minipro ...