Django中的ORM相关操作:F查询,Q查询,事物,ORM执行原生SQL
一 F查询与Q查询:
1 . F查询:
在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?
Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
示例1:
查询评论数大于收藏数的书籍
from django.db.models import F
models.Book.objects.filter(commnet_num__gt=F('keep_num'))
Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)
修改操作也可以使用F函数,比如将每一本书的价格提高30元
models.Book.objects.all().update(price=F("price")+30)
引申:
如果要修改char字段咋办?
如:把所有书名后面加上(第一版)
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("第一版"), Value(")")))
2 Q查询:
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象。
示例1:
查询作者名是杰克罗琳或王小波的
models.Book.objects.filter(Q(authors__name="杰克罗琳")|Q(authors__name="王小波"))
你可以组合& 和| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。
示例:查询作者名字是杰克罗琳并且不是2018年出版的书的书名。
>>> models.Book.objects.filter(Q(author__name="王小波") & ~Q(publish_date__year=2018)).values_list("title")
<QuerySet [('黄金时代',)]>
查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。
例如:查询出版年份是2017或2018,书名中带物语的所有书。
>>> models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="物语")
<QuerySet [<Book: 肖申克的救赎>, <Book: 黄金时代>, <Book: 白银时代>]>
3 事物:
数据库四大特性:
二.事务的 ACID
事务具有四个特征:原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )和持续性( Durability )。这四个特性简称为 ACID 特性。
1 、原子性
事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
2 、一致性
事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,
有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。
3 、隔离性
一个事务的执行不能被其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4 、持续性
也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响
import os if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
import django
django.setup() import datetime
from app01 import models
# 事务
# 买一本 人性的弱点一 书
# 在数据库层面要做的事儿
# 1. 创建一条订单数据
# 2. 去产品表 将卖出数+1, 库存数-1
from django.db.models import F
from django.db import transaction
# 开启事务处理
try:
with transaction.atomic():
# 创建一条订单数据
models.Order.objects.create(num="", product_id=1, count=1)
# 去产品表 将卖出数+1, 库存数-1 (报错)
# models.Product.objects.get(id=1).update(kucun=F("kucun")-1, maichu=F("maichu")+1)
# 能执行成功
models.Product.objects.filter(id=1).update(kucun=F("kucun")-1, maichu=F("maichu")+1)
except Exception as e:
print(e) # 不开启事务
# try:
# # 创建一条订单数据
# models.Order.objects.create(num="110110110", product_id=1, count=1)
# # 去产品表 将卖出数+1, 库存数-1
# models.Product.objects.get(id=1).update(kucun=F("kucun") - 1, maichu=F("maichu") + 1)
# except Exception as e:
# print(e)
关于事物的实际操作
Django中ORM执行原生的SQL:
# extra
# 在QuerySet的基础上继续执行子语句
# extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # select和select_params是一组,where和params是一组,tables用来设置from哪个表
# Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
# Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
# Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
# Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) 举个例子:
models.UserInfo.objects.extra(
select={'newid':'select count(1) from app01_usertype where id>%s'},
select_params=[1,],
where = ['age>%s'],
params=[18,],
order_by=['-age'],
tables=['app01_usertype']
)
"""
select
app01_userinfo.id,
(select count(1) from app01_usertype where id>1) as newid
from app01_userinfo,app01_usertype
where
app01_userinfo.age > 18
order by
app01_userinfo.age desc
""" # 执行原生SQL
# 更高灵活度的方式执行原生SQL语句
# from django.db import connection, connections
# cursor = connection.cursor() # cursor = connections['default'].cursor()
# cursor.execute("""SELECT * from auth_user where id = %s""", [1])
# row = cursor.fetchone()
Queryset方法大全:
##################################################################
# PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
################################################################## def all(self)
# 获取所有的数据对象 def filter(self, *args, **kwargs)
# 条件查询
# 条件可以是:参数,字典,Q def exclude(self, *args, **kwargs)
# 条件查询
# 条件可以是:参数,字典,Q def select_related(self, *fields)
性能相关:表之间进行join连表操作,一次性获取关联的数据。 总结:
1. select_related主要针一对一和多对一关系进行优化。
2. select_related使用SQL的JOIN语句进行优化,通过减少SQL查询的次数来进行优化、提高性能。 def prefetch_related(self, *lookups)
性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。 总结:
1. 对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。
2. prefetch_related()的优化方式是分别查询每个表,然后用Python处理他们之间的关系。 def annotate(self, *args, **kwargs)
# 用于实现聚合group by查询 from django.db.models import Count, Avg, Max, Min, Sum v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id'))
# SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1)
# SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1)
# SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1 def distinct(self, *field_names)
# 用于distinct去重
models.UserInfo.objects.values('nid').distinct()
# select distinct nid from userinfo 注:只有在PostgreSQL中才能使用distinct进行去重 def order_by(self, *field_names)
# 用于排序
models.UserInfo.objects.all().order_by('-id','age') def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
# 构造额外的查询条件或者映射,如:子查询 Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) def reverse(self):
# 倒序
models.UserInfo.objects.all().order_by('-nid').reverse()
# 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序 def defer(self, *fields):
models.UserInfo.objects.defer('username','id')
或
models.UserInfo.objects.filter(...).defer('username','id')
#映射中排除某列数据 def only(self, *fields):
#仅取某个表中的数据
models.UserInfo.objects.only('username','id')
或
models.UserInfo.objects.filter(...).only('username','id') def using(self, alias):
指定使用的数据库,参数为别名(setting中的设置) ##################################################
# PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
################################################## def raw(self, raw_query, params=None, translations=None, using=None):
# 执行原生SQL
models.UserInfo.objects.raw('select * from userinfo') # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名
models.UserInfo.objects.raw('select id as nid from 其他表') # 为原生SQL设置参数
models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,]) # 将获取的到列名转换为指定列名
name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) # 指定数据库
models.UserInfo.objects.raw('select * from userinfo', using="default") ################### 原生SQL ###################
from django.db import connection, connections
cursor = connection.cursor() # cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
row = cursor.fetchone() # fetchall()/fetchmany(..) def values(self, *fields):
# 获取每行数据为字典格式 def values_list(self, *fields, **kwargs):
# 获取每行数据为元祖 def dates(self, field_name, kind, order='ASC'):
# 根据时间进行某一部分进行去重查找并截取指定内容
# kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
# order只能是:"ASC" "DESC"
# 并获取转换后的时间
- year : 年-01-01
- month: 年-月-01
- day : 年-月-日 models.DatePlus.objects.dates('ctime','day','DESC') def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
# 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
# kind只能是 "year", "month", "day", "hour", "minute", "second"
# order只能是:"ASC" "DESC"
# tzinfo时区对象
models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai')) """
pip3 install pytz
import pytz
pytz.all_timezones
pytz.timezone(‘Asia/Shanghai’)
""" def none(self):
# 空QuerySet对象 ####################################
# METHODS THAT DO DATABASE QUERIES #
#################################### def aggregate(self, *args, **kwargs):
# 聚合函数,获取字典类型聚合结果
from django.db.models import Count, Avg, Max, Min, Sum
result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid'))
===> {'k': 3, 'n': 4} def count(self):
# 获取个数 def get(self, *args, **kwargs):
# 获取单个对象 def create(self, **kwargs):
# 创建对象 def bulk_create(self, objs, batch_size=None):
# 批量插入
# batch_size表示一次插入的个数
objs = [
models.DDD(name='r11'),
models.DDD(name='r22')
]
models.DDD.objects.bulk_create(objs, 10) def get_or_create(self, defaults=None, **kwargs):
# 如果存在,则获取,否则,创建
# defaults 指定创建时,其他字段的值
obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '','u_id': 2, 't_id': 2}) def update_or_create(self, defaults=None, **kwargs):
# 如果存在,则更新,否则,创建
# defaults 指定创建时或更新时的其他字段
obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '','u_id': 2, 't_id': 1}) def first(self):
# 获取第一个 def last(self):
# 获取最后一个 def in_bulk(self, id_list=None):
# 根据主键ID进行查找
id_list = [11,21,31]
models.DDD.objects.in_bulk(id_list) def delete(self):
# 删除 def update(self, **kwargs):
# 更新 def exists(self):
# 是否有结果 QuerySet方法大全
Queryset方法大全
其中批量插入:
import random
# list1 = []
# for i in range(4):
# list1.append(random.randint(65, 99)) # 批量插入
# ["66676869", "69656863", ...] data = ["".join([str(random.randint(65, 99)) for i in range(4)]) for j in range(100)]
# for i in data:
# models.A.objects.create(name=i) obj_list = [models.A(name=i) for i in data]
# 批量插入
models.A.objects.bulk_create(obj_list)
Django中的ORM相关操作:F查询,Q查询,事物,ORM执行原生SQL的更多相关文章
- django中数据库的相关操作
一.使用环境 python2.7,django>1.7 二.数据库进行配置 在setting文件中进行修改 1.找到DATABASES DATABASES = { 'default': { 'E ...
- Django中多表的增删改查操作及聚合查询、F、Q查询
一.创建表 创建四个表:书籍,出版社,作者,作者详细信息 四个表之间关系:书籍和作者多对多,作者和作者详细信息一对一,出版社和书籍一对多 创建一对一的关系:OneToOne("要绑定关系的表 ...
- Django框架详细介绍---ORM相关操作
Django ORM相关操作 官方文档: https://docs.djangoproject.com/en/2.0/ref/models/querysets/ 1.必须掌握的十三个方法 <1& ...
- Django学习笔记之Django ORM相关操作
一般操作 详细请参考官方文档 必知必会13条 <> all(): 查询所有结果 <> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 <> ...
- Django的F查询和Q查询,事务,ORM执行原生SQL
F查询和Q查询,事务及其他 F查询和Q查询 F查询 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个我们自己设定的常量做比较.如果我们要对两个字段的值做比较,那该怎么做呢? Django ...
- django系列5.5--分组查询,聚合查询,F查询,Q查询,脚本中调用django环境
一.聚合查询 aggregate(*args, **args) 先引入需要的包,再使用聚合查询 #计算所有图书的平均价格 from django.db.models import Avg Book.o ...
- python 之 Django框架(orm单表查询、orm多表查询、聚合查询、分组查询、F查询、 Q查询、事务、Django ORM执行原生SQL)
12.329 orm单表查询 import os if __name__ == '__main__': # 指定当前py脚本需要加载的Django项目配置信息 os.environ.setdefaul ...
- Django ORM 之F、Q查询与事务
返回ORM目录 Django ORM 内容目录 一.F.Q查询 二.事务 三.only与defer 一.F.Q查询 """ Product表中的数据: 1 橡皮 2 20 ...
- Django 08 Django模型基础3(关系表的数据操作、表关联对象的访问、多表查询、聚合、分组、F、Q查询)
Django 08 Django模型基础3(关系表的数据操作.表关联对象的访问.多表查询.聚合.分组.F.Q查询) 一.关系表的数据操作 #为了能方便学习,我们进入项目的idle中去执行我们的操作,通 ...
随机推荐
- [转]MyBatis中resultType与resultMap区别
MyBatis中关于resultType和resultMap的具体区别如下: MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap.resu ...
- openstack常见问题
openstack通过kolla-ansible添加一个计算节点,并部署后,发现控制节点上无法发现新加的计算节点, 在控制节点的 nova_scheduler.nova_api容器上执行发现计算节点 ...
- php 面向对象:this 关键字
PHP5中为解决变量的命名冲突和不确定性问题,引入关键字“$this”代表其所在当前对象. $this在构造函数中指该构造函数所创建的新对象. 在类中使用当前对象的属性和方法,必须使用$this-&g ...
- Python正则表达式指南 (转)
本文http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html 正则表达式经常被用到,而自己总是记不全,转载一份完整的以备不时之需. 1. ...
- JS 判断IE(转)
一.: 之前,js判断的方式都是利用浏览器的useragent字段.通过判断useragent字段里面是否包含有MSIE字段来判断是否是IE系列浏览器,屡试不爽. 但是在IE11之后,微软把自家的IE ...
- Zookeeper Ha集群简介+jdbcClient访问Ha集群环境
Hadoop-HA机制HA概述high available(高可用) 所谓HA(high available),即高可用(7*24小时不中断服务). 实现高可用最关键的策略是消除单点故障.HA严格来说 ...
- Application Request Route实现IIS Server Farms集群负载
首先你装一个web 平台安装程序:https://www.microsoft.com/zh-CN/download/details.aspx?id=6164 安装完之后会出现打开界面,iis中也可找到 ...
- C 500uS状态机架构
main int main(void) { InitSys(); SoftwareInit(); ) { if(P500usReq) { P500usReq = ; P500us(); } Modbu ...
- Python开发工具Atom
python基础教程之Python开发工具Atom 本节内容如下: Atom简介 下载安装Atom 安装Python开发包 使用Atom开发Python程序 Atom简介 Atom是Github开 ...
- Ubuntu使用操作记录/笔记
1.如何取得图形界面下的ROOT权限? 先alt+f2,然后 gksu nautilus 或者 kdesudo dolphin 2.如何使用Qt插件在Qt中进行ROS开发 http://blog.cs ...