[TimLinux] django model关于QuerySet
1. 获取执行过的sql命令
from django.db import connections
connections['default'].queries
2. 获取QuerySet将执行的sql语句
qs = Entries.object.all()
print(qs.query)
3. 单一模型:增删改查
模型示例:
from django.db import models
class Student(models.Model):
name = models.CharField(max_length=30)
sex = models.CharField(max_length=30)
3.1. 增
#构造函数方式增加数据
s1 = Student(name='Tim', sex='Male')
s1.save() #只有这步才执行了insert操作。 #管理对象方式增加数据
s1 = Student.objects.create() #已经执行了一次insert操作了。
s1.name = "Tim"
s1.sex = "Male"
s1.save() #这步是update操作
3.2. 删
# query set方式删除:这个方式,只执行了一次sql
qs = Student.objects.filter(pk=1) # 这个返回的是QuerySet
qs.delete() # 对象方式删除:这个方式,执行了两次sql
s1 = Student.objects.get(pk=1) # 这个返回的是RA对象
s1.delete()
3.3. 改
#直接在qs上操作数据的更新,对应的是sql的 update语句
from django.db import models
from django.db.models import functions
qs = Student.objects.filter(id__in=[1,2,3])
qs.update(name=functions.Concat('name', models.Value("appendStr"), output_field=models.CharField)) #操作对象的方式,对应的是,select,然后针对每一行,update。
qs = Student.objects.filter(id__in=[1,2,3])
for t in qs:
t.name = t.name + "appendStr"
t.save()
3.4. 查
查询接口分为两类,返回新的QuerySet对象的接口,和不返回QuerySet对象的接口,清单如下:
#返回新的QuerySet对象的接口
filter exclude annotate order_by reverse
distinct values values_list dates none
all union intersection difference select_related
prefetch_related extra defer only using
select_for_update raw #不返回QuerySet对象的接口
get create get_or_create update_or_create bulk_create
count in_bulk iterator latest earliest
first last aggregate exists update
delete as_manager
QuerySet特点:
- 链式过滤:
- 每一次过滤得到的QuerySet都是唯一的
- QuerySet是惰性的
QuerySet真实发生SQL操作的时机:
- 迭代操作:
- 切片操作:LIMIT SQL语句
- Pickling/Caching:
- repr()函数:
- len()函数:建议是用Count()
- list()函数:
- bool()函数:建议使用exists()
3.4.1. 返回QuerySet对象函数
- filter(**kwargs):只接收关键字参数,格式为Field lookup语法格式,多个参数间是 AND 关系,使用models.Q可以修改参数间的关系。
- exclude(**kwargs):与 filter 一样的参数格式,选择的方式为取反(NOT),是在整个参数之外增加NOT(参数逻辑),参数内还是 AND 关系
- annotate(*args, **kwargs):aggregate()是聚合操作,annotate则是在聚合的基础上进行了GROUP BY操作。针对的对象是:由”查询表达式”获取的QuerySet对象中的每一个对象。
- 查询表达式(Query Expressions):一个简单的值、模型(或关联模型)中的一个字段的引用、或者一个聚合表达式(Aggregate:avg,sum,count等)。查询表达式描述了一个值、或者一种运算:使用在更新(update)、创建(create)、过滤(filter)、排序(order by)、注解(annotate)、聚合(aggregate)中。许多内建表达式帮助我们写查询。表达式可以组合、或者在某些场景下嵌套来组成更复杂的运算。
- 支持数学运算:支持加、减、乘、除、取模数学运算,以及指数操作(使用Python常量、变量、或者其他表达式来实现)
- 加法:Company.objects.filter( num_employees__gt=F('num_chairs') + F('num_chairs) ) 字段值翻倍
- 乘法:Company.objects.filter( num_employees__gt=F('num_chairs') * 2 ) 字段值翻倍
- 减法:Company.objects.annotate( chairs_needed=F('num_employees') - F('num_chairs') )
- 内建表达式:被定义在 django.db.models.expressions 和 django.db.models.aggregates 中,通常import django.db.models即可使用
- F()表达式:数据库内,对字段进行运算操作,没必要将值先存入Python,然后再计算。F()表达式会在每次调用save()操作都执行一次
- Func()表达式:所以调用数据函数表达式的基础表达式。
- Aggregate()表达式:封装GROUP BY, 是其他聚合类Sum, Count等的父类。
- Value()表达式:表达式中需要传递值(整数、bool、字符串)时,直接使用Value对值进行转换后使用。
- ExpressionWrapper()表达式:简单包装另外一个表达式,并提供访问属性(output_field),F()表达式做算术运算时常用到。
- Subquery()表达式:添加子查询到一个QuerySet对象中。
- RawSQL表达式:无法写复杂的WHERE从句时,直接使用RawSQL表达式实现。
- 支持数学运算:支持加、减、乘、除、取模数学运算,以及指数操作(使用Python常量、变量、或者其他表达式来实现)
- QuerySet对象中的每一个对象:
- annotate中的每一个参数,都将被添加到QuerySet返回的每一个对象中。
- 关键字参数,将成为返回对象的属性名。
- 匿名参数,返回的对象属性名,将由"字段名__聚合函数名"组成,全小写格式。
- 只有聚合函数引用单一字段时,可以使用匿名参数,其他都必须使用关键字参数。
- 查询表达式(Query Expressions):一个简单的值、模型(或关联模型)中的一个字段的引用、或者一个聚合表达式(Aggregate:avg,sum,count等)。查询表达式描述了一个值、或者一种运算:使用在更新(update)、创建(create)、过滤(filter)、排序(order by)、注解(annotate)、聚合(aggregate)中。许多内建表达式帮助我们写查询。表达式可以组合、或者在某些场景下嵌套来组成更复杂的运算。
# 1. F()表达式
#--------------------------------
# 不好的操作方式
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1 # select stories_filed from reporter where name='Tintin'; 然后把字段存入Python内存,并处理
reporter.save() # update reporter set stories_filed=5 where id=1; 写入的时候是具体的值。 # 好的操作方式:使用F()表达式
from django.db.models import F
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save() # update reporter set stories_filed=stories_filed+1 where name='Tintin'; # 更好的方式:使用F()表达式
reporter = Repoters.objects.get(name='Tintin')
reporter.update( stories_filed=F('stories_filed') + 1 ) # 甚至一次操作所有对象
Repoters.objects.all().update( stories_filed=F('stories_filed') + 1 ) # F()表达式的注意事项:每次调用save都会执行F表达式,以下的示例,stories_filed将被增加2.
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save() reporter.name = 'Tintin Jr.'
reporter.save() # F()表达式还可以用在:filter、annotate中。 # 2. Func()表达式
#--------------------------------
# 所有函数都可以通过Func表达式来实现
from django.db.models import Func, F
queryset.annotate( field_lower=Func(F('field'), function='LOWER') ) # sql: SELECT ..., LOWER(field) AS field_lower FROM ... # 通过继承Func,实现自定义函数接口
class Lower(Func):
function = 'LOWER'
queryset.annotate( field_lower=Lower('field') ) # 3. Aggregate()表达式
#--------------------------------
# 是Func表达式的一个特定场景,使用GROUP BY从句,所有聚合函数都是继承自Aggregate表达式:Sum,Count。
# Aggregate是表达式、包装表达式,为此可以实现一些复杂的运算
Company.objects.annotate( managers_required=(Count('num_employees') / 4) + Count('num_managers') ) # 4. Value() 表达式
#--------------------------------
F('field') + 1 === F('field') + Value(1)
F('field') + '-append' # 这个会报错
F('field') + Value('-append') # 这样也会报错
Concat( 'field', Value('-append'), output_field=CharField ) # 这样就不会报错了 # 5. ExpressionWrapper()表达式
#--------------------------------
Ticket.objects.annotate( expires=ExpressionWrapper( F('active_at') + F('duration'), output_field=DateTimeField() ) ) # 6. Subquery() 表达式
#--------------------------------
# 给一个QuerySet添加一个明确的子查询
# OuterRef('pk') 引用外部QuerySet数据库中的pk字段, 与同一个model中的F()表达式类似
# 子查询需要使用values()指定返回单一的列属性值,以下例子只返回了 emails. newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
Post.objects.annotate(newest_commenter_email=Subquery(newest.values('emails')[:1]))
# PostgreSQL语句:
# SELECT post.id, (子查询在这里) AS newest_commenter_email FROM post;
# 子查询: SELECT comment.emails FROM comment WHERE comment.post_id=post.id ORDER BY created_at DESC LIMIT 1;
# Exists() 是Subquery()类的子类,使用的是SQL的 EXISTS语句
from django.db.models import Exists, OuterRef
from datetime import timedelta
from django.utils import timezone
one_day_ago = timezone.now() - timedelta(days=1)
recent_comments = Comment.objects.filter( post=OuterRef('pk'), created_at__gte=one_day_ago )
Post.objects.annotate( recent_comment=Exists(recent_comments) )
# PostgreSQL语句:
# SELECT post.id, post.published_at, EXISTS(子查询) AS recent_comment FROM post;
# 子查询:SELECT comment.id, comment.post_id, comment.email, comment.craeted_at FROM comment
# WHERE (comment.craeted_at >= YYYY-MM-DD HH:MM:SS AND comment.post_id=post.id); # 过滤子查询,需要先在annotate中运行子查询,然后filter过滤字段值
# 在子查询表达式中使用聚合 # 7. Raw SQL表达式
#--------------------------------
from django.db.models.expressions import RawSQL
queryset.annotate( val=RawSQL('select col from sometable where othercol=%s', (someparam,) )
- order_by:
- reverse:
- distinct:
- values:
- values_list:
- dates:
- datetimes:
- none:
- all:
- union:
- intersection:
- difference:
- select_related:
- prefetch_related:
- extra:
- defer:
- only:
- using:
- select_for_update:
- raw:
3.4.2. 不返回QuerySet对象函数
- get:
- create:
- get_or_create:
- update_or_create:
- bulk_create:
- count:
- in_bulk:
- iterator:
- latest:
- earliest:
- first:
- last:
- aggregate:
- exists:
- update:
- delete:
- as_manager:
3.5. Field查询
Field lookup:用来指定SQL查询中WHERE从句部分内容的,作为filter、exclude、get函数的关键字参数,格式:字段名__查询类型,字段名来自model的定义部分,然后带双下划线,接下来为Django语句支持的查询类型关键字:
# i开头表示,忽略大小写
# exact, 对应SQL语句: =
# iexact,对应SQL语句: LIKE (LIKE是不区分大小写的)
# contains,对应SQL语句: LIKE BINARY (LIKE BINARY是区分大小写的)
# icontain,对应SQL语句: LIKE exact iexact contains icontains in gt gte
lt lte startswith istartswith endswith iendswith range
date year month day week week_day time
hour minute second isnull search regex iregex #查询示例: name是字段名,exact是查询关键字,中间使用双下划线连接
Student.objects.filter(name__exact="tim")
# SQL: SELECT `student`.`id` `student`.`name` FROM `student` WHERE `student`.`name` = 'tim'; Student.objects.filter(name__iexact="tim")
# SQL: SELECT `student`.`id` `student`.`name` FROM `student` WHERE `student`.`name` LIKE 'tim';
Student.objects.filter(name__contain="tim")
# SQL: SELECT `student`.`id` `student`.`name` FROM `student` WHERE `student`.`name` LIKE BINARY '%tim%';
Student.objects.filter(name__icontain="tim")
# SQL: SELECT `student`.`id` `student`.`name` FROM `student` WHERE `student`.`name` LIKE '%tim%';
[TimLinux] django model关于QuerySet的更多相关文章
- django model ValueQuerySet QuerySet 转换成JSON
这里我有4个字段需要使用外键,那么在调取数据的时候就可以使用两个'_'进行调取,当然条件必须需要从前端传进来 models.py class HostInfo(models.Model): host_ ...
- Django:Model的Filter
转自:http://www.douban.com/note/301166150/ django model filter 条件过滤,及多表连接查询.反向查询,某字段的distinct 1.多表 ...
- Django Model数据访问Making queries
创建完Model之后, Django 自动为你提供一套数据库抽象层的API,利用它可以完成创建,提取,更新,删除对象的操作. 以下面的Model为例: class Blog(models.Model) ...
- django Model模型二及Model模型对数据库的操作
在django模型中负责与数据库交互的为Model层,Model层提供了一个基于orm的交互框架 一:创建一个最基本的Model from __future__ import unicode_lite ...
- Django Model field reference
===================== Model field reference ===================== .. module:: django.db.models.field ...
- Django model对象接口
Django model查询 # 直接获取表对应字段的值,列表嵌元组形式返回 Entry.objects.values_list('id', 'headline') #<QuerySet [(1 ...
- Django学习之四:Django Model模块
目录 Django Model 模型 MODEL需要在脑子里记住的基础概念 区分清楚,必须不能混淆的 class Meta 内嵌元数据定义类 简单model创建实例 数据源配置 接着通过models在 ...
- 提高django model效率的几个小方法
django的model效率不是很高,特别是在做大量的数据库操作的时候,如果你只用django来开企业站或者外包项目的话,那可以小跳过下,而你恰巧是效率狂或者说是对程序的效率要求比较高的话,那就要注意 ...
- Django Model 数据表
Django Model 定义语法 版本:1.7主要来源:https://docs.djangoproject.com/en/1.7/topics/db/models/ 简单用法 from djang ...
随机推荐
- day7-format字符串格式化
tpl = "i am {name}, age {age}, really {name}".format(name="seven", age=18) print ...
- Jenkins集群下的pipeline实战
关于Jenkins集群 在<快速搭建Jenkins集群>一文中,我们借助docker快速搭建了Jenkins集群,今天就在这个集群环境中创建pipeline任务,体验Jenkins集群下的 ...
- Java基础语法07-面向对象-多态
抽象类 抽象方法 : 没有方法体的方法. 抽象类:被abstract所修饰的类. 抽象类的语法格式: [权限修饰符] abstract class 类名{ }[权限修饰符] abstract clas ...
- secureCRT连接虚拟机
1.secureCRT英文版下载 链接:https://pan.baidu.com/s/1LFWD-k2r4ZB7DHQA66QogQ 密码:khmo 破解方式参考 2.虚拟机静态IP设置 参考 3. ...
- Centos内核参数优化
关于内核参数优化 net.ipv4.tcp_max_tw_buckets = 6000 net.ipv4.ip_local_port_range = 1024 65000 net.ipv4.tcp_ ...
- ansible-template
template简介 template功能: 根据模板文件动态生成对应的配置文件 template文件必须存放于templates目录下,且命名为 .j2 结尾 ansible的template模板使 ...
- 【评测机】评测时报错cc1plus: fatal error: /xx/xx/main.cpp: Permission denied compilation terminated.的解决方法
事情是这亚子发生的,原本建立评测机的时候就出现过这个问题,但莫名其妙就解决了. 报错的文件路径是位于docker内的,所以本质上这个错误是docker内的没有权限执行相关文件. 原因是centos7中 ...
- linux网络测试命令
一.ping 它通过向目标主机发送一个个数据包以及接受数据包的回应来判断主机和目标主机之间网络连接情况.ping的两个功能:判断网络是否可达.网络性能统计. ping使用的是网络层的ICMP协议. p ...
- 注意android辅助服务事件不能用于保存
本来希望把来自辅助服务的事件,像epoll那样暂存在队列进行调度,或者做成事件堆栈,从而将辅助服务事件加入到容器.但是一直不能达到预期的后果.最后才发现一个坑人的事实,辅助服务事件被释放(或者说重置) ...
- gcc在x64体系中如何传递参数,linux,mac,iOS适用
上一篇介绍了vc(windows)平台在x64体系当中,c函数的传参方式.本篇将要介绍gcc(类linux,mac)平台在x64中,c函数是如何传参的.为节约时间和篇幅,首先来定义一个有十个参数的函数 ...