一日一技:在Python里面实现链式调用

开发 后端
在这种写法里面,query对象有一个filter方法,这个方法的返回数据还可以继续调用filter方法,可以这样无限制地调用下去。

[[387344]]

我们在使用Django的models查询数据库时,可以看到有这种写法:

  1. form app.models import XXX 
  2. query = XXX.objects.all() 
  3. query = query.filter(name=123, age=456).filter(salary=999) 

在这种写法里面,query对象有一个filter方法,这个方法的返回数据还可以继续调用filter方法,可以这样无限制地调用下去。

这种写法是怎么实现的呢?

如果我们直接写一个类的方法,看看能不能这样调用:

  1. class Query: 
  2.     def filter(self): 
  3.         pass 
  4.  
  5. query = Query() 
  6. query.filter().filter() 

直接对query.filter()返回的结果再调用一次filter,就会导致报错了。这是因为在没有显式写return语句的时候,方法会返回None,而None对象是没有所谓的filter方法的。

那么什么东西有filter方法呢?显然我们的query对象有filter方法。那么如何让这个方法返回自身这个对象呢?

这个时候,我们就要看看我们在定义类方法的时候,总会写的的第一个参数self了。几乎每个类方法里面都会有它。大家只知道在类里面调用类方法的时候可以用self.xxx(),在调用类属性的时候可以用self.yy,那么有没有思考过,这个东西如果单独使用会怎么样呢?

实际上,self指的就是这个类实例化成一个对象以后,这个对象自身。而这个对象显然是有filter方法的。所以我们修改一下filter方法,让它返回self:

  1. class Query: 
  2.     def filter(self): 
  3.         return self 
  4.  
  5. query = Query() 
  6. query.filter().filter() 

从图中可以看出,现在已经不会报错了。那么回到最开始的问题,Django里面的链式调用传入查询参数是如何实现的呢?

实际上这里涉及到一个惰性查询的问题。

当我们不停调用.filter()方法的时候,Django会把这些查询条件全部缓存起来,只有当我们需要获取结果,或者查询满足条件的数据有多少条时,它才会真正地连接数据库去查询。

所以我们这里要模拟这个环境,把查询条件缓存起来。

那么为了获取调用方法时传入的参数名,我们就要使用**kwargs参数。这个参数可以接受所有的key=value形式的参数:

  1. class Query(): 
  2.     def __init__(self): 
  3.         self.query_condition = {} 
  4.  
  5.     def filter(self, **kwargs): 
  6.         self.query_condition.update(kwargs) 
  7.         return self 
  8.          
  9. query = Query() 
  10. a = query.filter(name='kingname').filter(age__gt=15, address='yyyyyy').filter(salary=99999) 
  11. print(query.query_condition) 

运行效果如下图所示:

 

在真正需要输出结果的时候,再使用这些缓存的条件,去数据库中查询结果即可。

本文转载自微信公众号「未闻Code」,可以通过以下二维码关注。转载本文请联系未闻Code公众号。

 

责任编辑:武晓燕 来源: 未闻Code
相关推荐

2021-09-13 20:38:47

Python链式调用

2021-07-27 21:32:57

Python 延迟调用

2021-10-06 23:17:26

Python抽象类接口

2024-02-20 22:13:48

Python项目Java

2022-06-28 09:31:44

LinuxmacOS系统

2021-04-12 21:19:01

PythonMakefile项目

2021-04-05 14:47:55

Python多线程事件监控

2021-05-12 00:12:37

Ocelot网关密码

2021-09-14 10:48:33

Ocelot网关

2021-10-15 21:08:31

PandasExcel对象

2021-04-27 22:15:02

Selenium浏览器爬虫

2022-06-09 21:34:41

Python代码函数

2021-01-22 05:47:21

Python关键字函数

2021-07-26 21:15:10

LRU缓存MongoDB

2022-05-16 20:18:41

商品数据监控

2020-05-19 13:55:38

Python加密密码

2021-06-08 21:36:24

PyCharm爬虫Scrapy

2023-10-28 12:14:35

爬虫JavaScriptObject

2022-03-12 20:38:14

网页Python测试

2021-04-19 23:29:44

MakefilemacOSLinux
点赞
收藏

51CTO技术栈公众号