深圳营销型网站开发,做流程图用什么网站,广州网站建设信科网络,应用商店app下载安装最新版软件一、Lookup API概述
Lookup API是Django用于构建数据库查询WHERE子句的API。
Lookup API的核心包含两部分#xff1a;
RegisterLookupMixin#xff1a;为子类提供注册lookup的方法Query Expression API#xff1a;一个接口#xff0c;规定了可以被注册为lookup的类需要实…一、Lookup API概述
Lookup API是Django用于构建数据库查询WHERE子句的API。
Lookup API的核心包含两部分
RegisterLookupMixin为子类提供注册lookup的方法Query Expression API一个接口规定了可以被注册为lookup的类需要实现的方法。
在Django中有两个实现了Query Expression API的基类分别是Lookup和Transform前者用于声明查询条件后者专注于对字段做转换。两者都实现了Query Expression API都可以被注册为lookup可以单独使用也可以互相配合。
lookup是一个比较抽象的名词它描述的是搜索和过滤条件而不是查找这个动作本身。对字段注册lookup我们就能构造查询表达语句Django会将其编译为合适的SQLWHERE子句。
二、Lookup基类
前面提到实现Query Expression API的基类分别是Lookup和Transform。首先介绍Lookup类它是我们构造查询语句的主力我们从自定义一个Lookup的子类出发来了解它的工作原理。
1. 自定义Lookup
尝试实现这样一件事情将User.objects.filter(username__isMario)转化为SQL:
user.username IS mario当然SQL语句中不存在IS这样只是方便理解。实现这个功能需要两个步骤
声明一个Lookup的子类并重写as_sql()方法
from django.db.models import Lookupclass Is(Lookup):lookup_name isdef as_sql(self, compiler, connection):lhs, lhs_params self.process_lhs(compiler, connection)rhs, rhs_params self.process_rhs(compiler, connection)params lhs_params rhs_paramsreturn %s IS %s % (lhs, rhs), params注册新声明的lookup类Is 需要lookup在某个字段上生效就需要调用这个字段上的register_lookup方法进行注册。Filed继承了RegisterLookupMixin类因此可以使用其提供的register_lookup方法注册lookup。为Field注册lookup其所有子类就都可以使用此lookup
from django.db.models import FieldField.register_lookup(Is)Filed提供了装饰器方法注册lookup
from django.db.models import FieldField.register_lookup
class Is(Lookup): ...使用新定义的Is查找类的方法有两种
构造lhs__lookup_namerhs形式的查询表达语句
from django.contrib.auth.models import User
q User.objects.filter(username__ismairo)
q.query
print(q.query)编译的SQL语句
SELECT ...略 FROM auth_user WHERE auth_user.username IS mairo使用创建实例的形式
q User.objects.filter(username__ismairo)from django.db.models import F
q2 User.objects.filter(Is(F(username), mario))编译的SQL语句与上面的方法完全一致两种方法是等效的。
2. Django内置的lookup
Django内置了很多lookup在django.db.models.lookups目录下你可以找到它们
...
Field.register_lookup
class GreaterThan(FieldGetDbPrepValueMixin, BuiltinLookup):lookup_name gtField.register_lookup
class GreaterThanOrEqual(FieldGetDbPrepValueMixin, BuiltinLookup):lookup_name gte
...介绍两种常用的内置lookup:
exact 默认情况下当你没有提供查找类型的时候默认使用exact:
Entry.objects.get(id14)
Entry.objects.get(id__exact14)
# 上面两个完全一致准确来说django将id14默认视为id__exact14等效SQL语句:
SELECT ... WHERE id 14;in
Entry.objects.filter(id__in[1, 3, 4])等效SQL语句
SELECT ... WHERE id IN (1, 3, 4);三、Transform基类
与Lookup类相同Transform类及其子类也可以被注册为lookup但Transform与Lookup不同Transform 更加关注的是如何改变字段值而不是直接进行值的比较。通过使用 Transform你可以对数据库中的数据执行诸如转换为小写、截取字符串的一部分、日期时间的格式化等操作。通常会和Lookup配合使用它主要做预处理工作。它是数据库级别的转换具有很好的性能。
1. 自定义Transform
from django.db.models import Transform
from django.db.models import IntegerFieldclass AbsoluteValue(Transform):lookup_name absfunction ABSIntegerField.register_lookup(AbsoluteValue)Transform在源码中继承了两个类class Transform(RegisterLookupMixin, Func)可以说它是一个特殊的Func在声明时就规定好了用于转换的function因此只接收一个参数。
使用示例1
Experiment.objects.filter(change__abs27)生成的SQL
SELECT ... WHERE ABS(experiments.change) 27注意这里django实际上将change__abs27 视作 change__abs__exact27。
使用示例2
Experiment.objects.filter(change__abs__lt27)生成的SQL:
SELECT ... WHERE ABS(experiments.change) 272. 内置的Transform
year
Blog.objects.filter(time__year__gt2023)生成的SQL
SELECT ... FROM snippets_blog WHERE snippets_blog.time 2023-12-31 23:59:59.99999900:00Django内置了很多中方便的transform这里不做赘述。
四、lookup表达语句的构成
一个lookup表达语句可以由三部分构成组合使用可以构造强大高效的查询语句。
field如Book.objects.filter(author__best_friends__first_name...)Transform如__lower__first3chars__reversedlookup如__icontains默认__exact
五、总结
lookup API是Django中一个很重要的功能它的主要工作就是构造查询的WHERE子句。Django已经内置了很多使用的lookups帮助我们快速构造查询语句。Django允许我们自定义lookups实现复杂的查询需求。