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表达式实现。
    • QuerySet对象中的每一个对象:
      • annotate中的每一个参数,都将被添加到QuerySet返回的每一个对象中。
      • 关键字参数,将成为返回对象的属性名。
      • 匿名参数,返回的对象属性名,将由"字段名__聚合函数名"组成,全小写格式。
      • 只有聚合函数引用单一字段时,可以使用匿名参数,其他都必须使用关键字参数。
# 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的更多相关文章

  1. django model ValueQuerySet QuerySet 转换成JSON

    这里我有4个字段需要使用外键,那么在调取数据的时候就可以使用两个'_'进行调取,当然条件必须需要从前端传进来 models.py class HostInfo(models.Model): host_ ...

  2. Django:Model的Filter

    转自:http://www.douban.com/note/301166150/   django model filter 条件过滤,及多表连接查询.反向查询,某字段的distinct   1.多表 ...

  3. Django Model数据访问Making queries

    创建完Model之后, Django 自动为你提供一套数据库抽象层的API,利用它可以完成创建,提取,更新,删除对象的操作. 以下面的Model为例: class Blog(models.Model) ...

  4. django Model模型二及Model模型对数据库的操作

    在django模型中负责与数据库交互的为Model层,Model层提供了一个基于orm的交互框架 一:创建一个最基本的Model from __future__ import unicode_lite ...

  5. Django Model field reference

    ===================== Model field reference ===================== .. module:: django.db.models.field ...

  6. Django model对象接口

    Django model查询 # 直接获取表对应字段的值,列表嵌元组形式返回 Entry.objects.values_list('id', 'headline') #<QuerySet [(1 ...

  7. Django学习之四:Django Model模块

    目录 Django Model 模型 MODEL需要在脑子里记住的基础概念 区分清楚,必须不能混淆的 class Meta 内嵌元数据定义类 简单model创建实例 数据源配置 接着通过models在 ...

  8. 提高django model效率的几个小方法

    django的model效率不是很高,特别是在做大量的数据库操作的时候,如果你只用django来开企业站或者外包项目的话,那可以小跳过下,而你恰巧是效率狂或者说是对程序的效率要求比较高的话,那就要注意 ...

  9. Django Model 数据表

    Django Model 定义语法 版本:1.7主要来源:https://docs.djangoproject.com/en/1.7/topics/db/models/ 简单用法 from djang ...

随机推荐

  1. [LINQ2Dapper]最完整Dapper To Linq框架(四)---Linq和SQL并行使用

    目录 [LINQ2Dapper]最完整Dapper To Linq框架(一)---基础查询 [LINQ2Dapper]最完整Dapper To Linq框架(二)---动态化查询 [LINQ2Dapp ...

  2. Linux基础命令(二)

    6.cp copy 作用:复制文件 选项: -a 复制目录时使用并且可以保持属性不变,属性:属主,属组,权限 -r 复制目录时使用但是不可以保持属性不变 -p 保持属性不变 注意:其实只需要记一个-a ...

  3. ios input输入不了

    在项目中遇到了一个问题就是input输入框在安卓可以输入,而在ios输入不了 经过百度,调试发现,在ios中input默认是有user-select: none;属性把input输入框禁用了,将其删除 ...

  4. tornado的使用-参数篇

    tornado的使用-参数篇

  5. pat 1011 World Cup Betting(20 分)

    1011 World Cup Betting(20 分) With the 2010 FIFA World Cup running, football fans the world over were ...

  6. iOS界面流畅技巧之微博 Demo 性能优化技巧

    微博 Demo 性能优化技巧 我为了演示 YYKit 的功能,实现了微博和 Twitter 的 Demo,并为它们做了不少性能优化,下面就是优化时用到的一些技巧. 预排版 当获取到 API JSON ...

  7. dom4j的测试例子和源码详解(重点对比和DOM、SAX的区别)

    目录 简介 DOM.SAX.JAXP和DOM4J xerces解释器 SAX DOM JAXP DOM解析器 获取SAX解析器 DOM4j 项目环境 工程环境 创建项目 引入依赖 使用例子--生成xm ...

  8. C++学习第一天(打卡)

    C++和C最大的区别可能就是添加了面向对象的编程. using namespace std 是其中oop的一个特性. using namespace std 可以使程序使用std名称空间里面的定义. ...

  9. Spring中常见的设计模式——原型模式

    1.原型模式应用场景 当遇到大量耗费劳动力的 get,set赋值场景时,如下: public class SetGetParam { public void setParam(UserDto user ...

  10. day 41 css固定位置 以及小米商城项目

    .如何让一个绝对定位的盒子居中 left:%; margin-left:- 宽度的一半 .固定定位 position: fixed; ()脱标 参考点:浏览器的左上角 作用:固定导航栏 返回顶部 小广 ...