django的F和Q对象
F表达式和Q表达式:
# 示例模型如下
class Book(models.Model):
"""图书模型"""
name = models.CharField(max_length=300)
pages = models.IntegerField()
price = models.FloatField()
rating = models.FloatField()
author = models.ForeignKey(Author, on_delete=models.CASCADE)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
class Meta:
db_table = 'book'
class Author(models.Model):
"""作者模型"""
name = models.CharField(max_length=100)
age = models.IntegerField()
email = models.EmailField()
class Meta:
db_table = 'author'
F表达式:
F表达式是用来优化django的orm操作数据库的,使用F表达式时,F表达式就像是一个标记,F表达式不会立刻去提取数据库的值,他会在查询数据库的时候动态的获取F表达式中字段的值,这样的操作很明显会提高orm操作的效率,F表达式可以提取连表中的数据,此时所使用的字段形式和查询连表中的字段形式相同,会使用XXX__字段的方式。
现在有一个需求,把图书的售价在原来的基础上增加10元,如果我们不用F表达式,那么操作应该是先从数据库中提取所有的图书售价到Python内存中,然后使用Python代码在图书售价的基础之上增加10元,最后再保存到数据库中,示例代码如下:
books = Book.objects.all()
for book in books:
book.price += 10
book.save()
上面这种操作,在效率上显然不是很高,现在我们使用F表达式进行操作,示例代码如下:
from django.db.models import F
Book.objects.update(price=F('price')+10)
print(connection.queries[-1]['sql'])
原生SQL:UPDATE `book` SET `price` = (`book`.`price` + 10)
由上面的操作,很明显的可以看出F表达式相对与常规操作的简便和高效,其实从上面的操作可以看出F表达式在执行的时候类似for循环的逐条执行,只不过这里的SQL更简单,为了说明逐条执行的特点,我们再提出一个需求,就是查询出Author模型中,name与email相同的所有作者,常规操作如下:
authors = Author.objects.all()
for author in authors:
if author.name == author.email:
print(author)
使用F表达式操作如下:
authors = Author.objects.filter(name=F('email')) # 注意name和email两个字段只需要在一个上使用F表达式
for author in authors:
print(author)
原生SQL:SELECT `author`.`id`, `author`.`name`, `author`.`age`, `author`.`email` FROM `author` WHERE `author`.`name` = (`author`.`email`) LIMIT 21
有的时候,我们需要对特定的字段做一些批量的拼接处理,例如在所有图书名称后面加上'(售)'这样的字符串,这种拼接,django的F表达式也是可以帮我们完成的,这时候需要使用Concat连接,例如在所有的图书名称后面加上'(售)'这样的字符,这样的需求我们既可以使用Concat来完成,示例代码如下:
from django.db.models.functions inport Concat
from django.db.models import Value
Book.objects.update(name=Concat(F('name'),Value('('),Value('售'),Value(')')))
原生SQL:UPDATE `book` SET `name` = CONCAT_WS('', `book`.`name`, CONCAT_WS('', '(', CONCAT_WS('', '售', ')')))
注:这里使用F表达式动态的逐条获取'name'字段,然后使用Concat连接动态取出的name与其他字符串
Q表达式:
Q表达式通过传递字段的过滤条件,以及多个Q表达式连接使用,以实现复杂的查询操作,同时也弥补了在使用多个字段作为查询条件时无法使用或的方式。这些条件在之前博客https://www.cnblogs.com/limaomao/p/9302331.html中有具体的介绍,这里就不一一赘述了。Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
Q表达式之间可以使用 与(&)、或(|)、非(~)进行查询条件的组合,Q表达式中的非(~)弥补了过滤条件中没有不等与(没有__ne)或者不包含(没有__nc)的缺陷,Q 表达式当然也可以单独作为条件使用:
1、查找出name中包含'传'字的所有图书:
books = Book.objects.filter(Q(name__contains='传'))
原生SQL:SELECT `book`.`id`, `book`.`name`, `book`.`pages`, `book`.`price`, `book`.`rating`, `book`.`author_id`, `book`.`publisher_id` FROM `book` WHERE `book`.`name` LIKE BINARY '%传%' LIMIT 21
2、查找出定价低于100并且评分低于4.5分的所有图书
books = Book.objects.filter(Q(price__lt=100) & Q(rating__lt=4.5))
3、查找出定价低于100或者评分低于4.5分的所有图书
books = Book.objects.filter(Q(price__lt=100) | Q(rating__lt=4.5))
4、获取所有name不包含'记'的图书
books = Book.objects.filter(~Q(name__icontains='记'))
5、获取书名包含“记”,但是id不等于3的图书
books = Book.objects.filter(Q(name__icontains='记') & ~Q(id=3))
6、Q对象可以与关键字参数查询一起使用,必须把普通关键字查询放到Q对象查询的后面
Book.objects.filter(Q(price=70)|Q(title="Python"), publication_date="2017-09-26")
django的F和Q对象的更多相关文章
- Django运算表达式与Q对象/F对象
Django运算表达式与Q对象/F对象 1 模型查询 概述: 1 查询集:表示从数据库中获取的对象的集合 2 查询集可以有多个过滤器,通过 逻辑运算符连接 3 过滤器就是一个函数,基于所给的参数限制查 ...
- Django之F、Q查询,事务,自定义char字段
F查询 from django.db.models import F,Q # 当查询条件来自于数据库的某个字段,这个时候就必须使用F # 查询卖出数大于库存数的商品 res = models.Prod ...
- Django之F和Q查询
一.F查询 rom django.db.models import F from app01.models import Book Book.objects.update(price=F(" ...
- Django之F与Q查询
F查询 from django.db.models import F,Q # 1.查询库存数大于卖出数的书籍 res = models.Book.objects.filter(kucun__gt=F( ...
- django之 F与Q查询
F与Q查询 F查询 why?
- django【F和Q】
一.F 案例每人增加500工资 ORM:UserInfo.objects.filter().update(salary=500) 这不行吧 SQL: update userinfo set salar ...
- 第三百零九节,Django框架,models.py模块,数据库操作——F和Q()运算符:|或者、&并且——queryset对象序列化
第三百零九节,Django框架,models.py模块,数据库操作——F()和Q()运算符:|或者.&并且 F()可以将数据库里的数字类型的数据,转换为可以数字类型 首先要导入 from dj ...
- Django 08 Django模型基础3(关系表的数据操作、表关联对象的访问、多表查询、聚合、分组、F、Q查询)
Django 08 Django模型基础3(关系表的数据操作.表关联对象的访问.多表查询.聚合.分组.F.Q查询) 一.关系表的数据操作 #为了能方便学习,我们进入项目的idle中去执行我们的操作,通 ...
- 七 Django框架,models.py模块,数据库操作——F和Q()运算符:|或者、&并且——queryset对象序列化
F()可以将数据库里的数字类型的数据,转换为可以数字类型 首先要导入 from django.db.models import F from django.shortcuts import rende ...
随机推荐
- python剑指offer最小的K个数
题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 思路: 使用快排中的partition思想. ①我们设定part ...
- EF Database first 中,实现 多个表对应一个 实体的 查询
1.首先 创建好 数据 库. hobby表 major 表 student 表 外键 关系如下 2. 实现将 数据库 映射到EDM中 视图如下 在VS中 生成了 3个实体类 ,对应的是 数据库中的3 ...
- javaweb基础(39)_数据库连接池
一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...
- 解决cdh4.5.0下 MAP任务看不到状态
参考 http://qnalist.com/questions/772595/yarn-jobhistory-service 在mapreduce-site.xml中添加 <property&g ...
- 第31章 TIM—基本定时器—零死角玩转STM32-F429系列
第31章 TIM—基本定时器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...
- java面试题:已知一个数组[2,4,6,2,1,5],将该数组进行排序(降序,不能用工具类进行排序),创建两条线程交替输出排序后的数组,线程名自定义
package com.swift; import java.util.Arrays; import java.util.Comparator; public class ArrayThread_Te ...
- Python线程间事件通知
Python事件机制 事件机制:这是线程间最简单的通信机制:一个线程发送事件,其他线程等待事件事件机制使用一个内部的标志,使用set方法进行使能为True,使用clear清除为falsewait方法将 ...
- 爬虫学习(十六)——jsonpath
jsonpath介绍 jsonpath是一种信息抽取类库,是从json文档中抽取指定信息的工具,提供多种语言实现的版本 jsonpath对json来说,就相当于xpath对于xml jsonpath和 ...
- python代码实现截图识字
有次网上down了个截图实识的软件,发现一天只能用10次要钱才能解锁免费,很气,作为一个菜鸡怎么能忍受 于是自己用python写了个简单的小工具,分享给大家 代码如下: 先安装库 from PIL i ...
- php中==和===的含义及区别
===比较两个变量的值和类型:==比较两个变量的值,不比较数据类型. 比如 $a = '123'; $b = 123; $a === $b为假: $a == $b为真: 有些情况下不能使用==,可以使 ...