这篇文档是查找 API 的参考,Django 用这些API 构建数据库查询的WHERE 子句。若要学习如何使用 查找,参见执行查询;若要了解如何创建 新的查找,参见自定义查找。
查找 API 由两个部分组成:RegisterLookupMixin 类,它用于注册查找;查询表达式API,它是一个方法集,类必须实现它们才可以注册成一个查找。
Django 有两个类遵循查询表达式API,且Django 所有内建的查找都继承自它们:
查找表达式由三部分组成:
Django 使用RegisterLookupMixin 来为类提供接口,注册它自己的查找。两个最突出的例子是Field(所有模型字段的基类)和 Aggregate(Django 所有聚合函数的基类)。
一个mixin,实现一个类上的查找API。
在类中注册一个新的查找。例如,DateField.register_lookup(YearExact) 将在DateField 上注册一个 YearExact查找。它会覆盖已存在的同名查找。
查询表达式API是一个通用的方法集,定义了这些方法的类可以使用该方法集来将它们自身转换为SQL表达式。直接的字段引用,聚合,以及Transform类都是遵循这个API的示例。当一个对象实现以下方法时,就被称为遵循查询表达式API:
负责从表达式中产生查询字符串和参数。compiler是一个SQLCompiler对象,它拥有可以编译其它表达式的compile()方法。connection是用于执行查询的连接。
调用expression.as_sql()一般是不对的 -- 而是应该调用compiler.compile(expression)。 compiler.compile()方法应该在调用表达式的供应商特定方法时格外小心。
和as_sql()的工作方式类似。当一个表达式经过compiler.compile()编译之后, Django会首先尝试调用as_vendorname(),其中vendorname是用于执行查询的后端供应商。对于Django内建的后端,vendorname是postgresql,oracle,sqlite,或者mysql之一。
必须返回名称为lookup_name的查找。例如,通过返回self.output_field.get_lookup(lookup_name)来实现。
必须返回名称为transform_name的查找。例如,通过返回self.output_field.get_transform(transform_name)来实现。
Transform是用于实现字段转换的通用类。一个显然的例子是__year会把DateField转换为IntegerField。
在表达式中执行查找的标记是Transform<expression>__<transformation> (例如 date__year)。
这个类遵循查询表达式API,也就是说你可以使用 <expression>__<transform1>__<transform2>。
一个布尔值,表明是否对lhs和 rhs都应用这个转换。如果对两侧都应用转换,应用在rhs的顺序和在查找表达式中的出现顺序相同。默认这个属性为False。使用方法的实例请见自定义查找。
查找的名称,用于在解析查询表达式的时候识别它。
需要被覆写;否则抛出NotImplementedError异常。
和get_lookup()相同。
和get_transform()相同。
Lookup是实现查找的通用的类。查找是一个查询表达式,它的左边是lhs,右边是rhs;lookup_name用于构造lhs和rhs之间的比较,来产生布尔值,例如lhs in rhs或者lhs > rhs。
在表达式中执行查找的标记是<lhs>__<lookup_name>=<rhs>。
这个类并不遵循查询表达式API,因为在它构造的时候出现了=<rhs>:查找总是在查找表达式的最后。
在右边,也就是用来和lhs比较的东西。它可以是个简单的值,也可以是在SQL中编译的一些东西,比如 F() 对象或者QuerySet。
查找的名称,用于在解析查询表达式的时候识别它。
返回元组(lhs_string, lhs_params),和compiler.compile(lhs)所返回的一样。这个方法可以被覆写,来调整lhs的处理方式。
compiler是一个SQLCompiler对象,可以像 compiler.compile(lhs)这样使用来编译lhs。connection可以用于编译供应商特定的SQL语句。lhs如果不为None, 会代替self.lhs作为处理后的lhs使用。
对于右边的东西,和process_lhs()的行为相同。
2015年5月13日