python中如何实现链式调用
作者:kingname 发布时间:2021-05-06 08:42:29
我们在使用Django的models查询数据库时,可以看到有这种写法:
form app.models import XXX
query = XXX.objects.all()
query = query.filter(name=123, age=456).filter(salary=999)
在这种写法里面,query对象有一个filter
方法,这个方法的返回数据还可以继续调用filter
方法,可以这样无限制地调用下去。
这种写法是怎么实现的呢?
如果我们直接写一个类的方法,看看能不能这样调用:
class Query:
def filter(self):
pass
query = Query()
query.filter().filter()
直接对query.filter()
返回的结果再调用一次filter
,就会导致报错了。这是因为在没有显式写return语句的时候,方法会返回None
,而None对象是没有所谓的filter
方法的。
那么什么东西有filter方法呢?显然我们的query对象有filter方法。那么如何让这个方法返回自身这个对象呢?
这个时候,我们就要看看我们在定义类方法的时候,总会写的的第一个参数self
了。几乎每个类方法里面都会有它。大家只知道在类里面调用类方法的时候可以用self.xxx()
,在调用类属性的时候可以用self.yy
,那么有没有思考过,这个东西如果单独使用会怎么样呢?
实际上,self
指的就是这个类实例化成一个对象以后,这个对象自身。而这个对象显然是有filter
方法的。所以我们修改一下filter
方法,让它返回self
:
class Query:
def filter(self):
return self
query = Query()
query.filter().filter()
从图中可以看出,现在已经不会报错了。那么回到最开始的问题,Django里面的链式调用传入查询参数是如何实现的呢?
实际上这里涉及到一个惰性查询
的问题。
当我们不停调用.filter()
方法的时候,Django会把这些查询条件全部缓存起来,只有当我们需要获取结果,或者查询满足条件的数据有多少条时,它才会真正地连接数据库去查询。
所以我们这里要模拟这个环境,把查询条件缓存起来。
那么为了获取调用方法时传入的参数名,我们就要使用**kwargs
参数。这个参数可以接受所有的key=value形式的参数:
class Query():
def __init__(self):
self.query_condition = {}
def filter(self, **kwargs):
self.query_condition.update(kwargs)
return self
query = Query()
a = query.filter(name='kingname').filter(age__gt=15, address='yyyyyy').filter(salary=99999)
print(query.query_condition)
运行效果如下图所示:
在真正需要输出结果的时候,再使用这些缓存的条件,去数据库中查询结果即可。
来源:https://mp.weixin.qq.com/s/LmTO6WL6stw3S5-WWJ6s6A


猜你喜欢
- Juan Pablo De Gregorio 的 原文很多人都问我如何为一本杂志、一份报纸、一张海报、一份简报或是一份出版物选择
- 主键与外键的关系,通俗点儿讲,我现在有一个论坛,有两张表,一张是主贴 thread,一张是回帖 reply先说说主键,主键是表里面唯一识别记
- 本文实例为大家分享了python脚本筛选出两个文件中重复的行数,供大家参考,具体内容如下'''查找A文件中,与B文件
- f-string 格式化f-string 格式化 就是在字符串模板前面加上f,然后占位符使用{} ,里面直接放入对应的数据对象。如下所示f&
- 使用zap接收gin框架默认的日志并配置日志归档我们在基于gin框架开发项目时通常都会选择使用专业的日志库来记录项目中的日志,go语言常用的
- sys 模块提供了许多函数和变量来处理 Python 运行时环境的不同部分.处理命令行参数在解释器启动后, argv 列表包含了传递给脚本的
- 前言:在日常开发的过程中,有时候会临时用到一些简单的函数,她们的业务逻辑会相对简单,简单到并不值得让他们留下名字,这个时候,就很值得使用匿名
- 1、首先介绍简单的try......except尝试运行的放例如下面的图和代码来简单介绍下:def test(x,y): pri
- 无意中看到一段用Tkinter库写的放烟花的程序,就跟着跑了一遍。设计理念:通过让画面上一个粒子分裂为X数量的粒子来模拟 * 效果。粒子会发生
- 目录最终版本过程借鉴代码思考urllib.request和requestsBeautifulSoup优化处理总结代码复制可直接使用,记得pi
- 例如:from multiprocessing import Pooldef f(x):return x*xpool = Pool(proc
- ucky-canvas 介绍一个基于 Js + Canvas 的【大转盘 & 九宫格 & * 】抽奖, 致力于为 web
- 一、复习首先将上次画的矩形做复杂一些的小程序:import pygame,sys, randompygame.init()screen =
- python包-pdfkit 将HTML转换为PDF什么是pdfkitpdfkit,把HTML+CSS格式的文件转换成PDF格式文档的一种工
- 1.C++ 代码Demo.h#pragma oncevoid GeneratorGaussKernel(int ksize, float s
- MySQL存储过程SAVEPOINT ROLLBACK to示例如下:DELIMITER $$DROP PROCEDURE IF EXIST
- php多进程实现PHP有一组进程控制函数(编译时需要–enable-pcntl与posix扩展),使得php能在nginx系统中实现跟c一样
- 1.贴题题目来自PythonTip 信息加密给你个小写英文字符串a和一个非负数b(0<=b<26), 将a中的每个小写字符替换成
- //只能在firefox下运行 var test = { name: "puterjam", __noSuchMetho
- 使用python批量修改文本文件编码格式把文本文件的编码格式进行批量幻化,比如ascii, gb2312, utf8等,相互转化,字符集的大