New in Django 1.7.
這篇文檔是查找 API 的參考,Django 用這些API 構(gòu)建數(shù)據(jù)庫(kù)查詢的WHERE
子句。若要學(xué)習(xí)如何使用 查找,參見(jiàn)執(zhí)行查詢;若要了解如何創(chuàng)建 新的查找,參見(jiàn)自定義查找。
查找 API 由兩個(gè)部分組成:RegisterLookupMixin
類,它用于注冊(cè)查找;查詢表達(dá)式API,它是一個(gè)方法集,類必須實(shí)現(xiàn)它們才可以注冊(cè)成一個(gè)查找。
Django 有兩個(gè)類遵循查詢表達(dá)式API,且Django 所有內(nèi)建的查找都繼承自它們:
Lookup
:用于查找一個(gè)字段(例如field_name__exact
中的exact
)Transform
:用于轉(zhuǎn)換一個(gè)字段查找表達(dá)式由三部分組成:
Book.objects.filter(author__best_friends__first_name...)
;__lower__first3chars__reversed
);__icontains
),如果省略則默認(rèn)為__exact
。Django 使用RegisterLookupMixin
來(lái)為類提供接口,注冊(cè)它自己的查找。兩個(gè)最突出的例子是Field
(所有模型字段的基類)和 Aggregate
(Django 所有聚合函數(shù)的基類)。
class lookups.RegisterLookupMixin
一個(gè)mixin,實(shí)現(xiàn)一個(gè)類上的查找API。
classmethod register_lookup(lookup)
在類中注冊(cè)一個(gè)新的查找。例如,DateField.register_lookup(YearExact)
將在DateField
上注冊(cè)一個(gè) YearExact
查找。它會(huì)覆蓋已存在的同名查找。
get_lookup(lookup_name)
返回類中注冊(cè)的名為lookup_name
的 Lookup
。默認(rèn)的實(shí)現(xiàn)會(huì)遞歸查詢所有的父類,并檢查它們中的任何一個(gè)是否具有名稱為lookup_name
的查找,并返回第一個(gè)匹配。
get_transform(transform_name)
返回一個(gè)名為transform_name
的Transform
。默認(rèn)的實(shí)現(xiàn)會(huì)遞歸查找所有的父類,并檢查它們中的任何一個(gè)是否具有名稱為transform_name
的查找,并返回第一個(gè)匹配。
一個(gè)類如果想要成為查找,它必須實(shí)現(xiàn)查詢表達(dá)式API。Lookup
和Transform
一開始就遵循這個(gè)API。
查詢表達(dá)式API是一個(gè)通用的方法集,在查詢表達(dá)式中可以使用定義了這些方法的類,來(lái)將它們自身轉(zhuǎn)換為SQL表達(dá)式。直接的字段引用,聚合,以及Transform
類都是遵循這個(gè)API的示例。當(dāng)一個(gè)對(duì)象實(shí)現(xiàn)以下方法時(shí),就被稱為遵循查詢表達(dá)式API:
as_sql(self, compiler, connection)
負(fù)責(zé)從表達(dá)式中產(chǎn)生查詢字符串和參數(shù)。compiler
是一個(gè)SQLCompiler
對(duì)象,它擁有可以編譯其它表達(dá)式的compile()
方法。connection
是用于執(zhí)行查詢的連接。
調(diào)用expression.as_sql()
一般是不對(duì)的 -- 而是應(yīng)該調(diào)用compiler.compile(expression)
。 compiler.compile()
方法應(yīng)該在調(diào)用表達(dá)式的供應(yīng)商特定方法時(shí)格外小心。
as_vendorname(self, compiler, connection)
和as_sql()
的工作方式類似。當(dāng)一個(gè)表達(dá)式經(jīng)過(guò)compiler.compile()
編譯之后, Django會(huì)首先嘗試調(diào)用as_vendorname()
,其中vendorname
是用于執(zhí)行查詢的后端供應(yīng)商。對(duì)于Django內(nèi)建的后端,vendorname
是postgresql
,oracle
,sqlite
,或者mysql
之一。
get_lookup(lookup_name)
必須返回名稱為lookup_name
的查找。例如,通過(guò)返回self.output_field.get_lookup(lookup_name)
來(lái)實(shí)現(xiàn)。
get_transform(transform_name)
必須返回名稱為transform_name的
查找。例如,通過(guò)返回self.output_field.get_transform(transform_name)
來(lái)實(shí)現(xiàn)。
output_field
定義get_lookup()
方法所返回的類的類型。必須為Field
的實(shí)例。
class Transform
Transform
是用于實(shí)現(xiàn)字段轉(zhuǎn)換的通用類。一個(gè)顯然的例子是__year
會(huì)把DateField
轉(zhuǎn)換為IntegerField
。
在表達(dá)式中執(zhí)行查找的標(biāo)記是Transform<expression>__<transformation>
(例如 date__year
)。
這個(gè)類遵循查詢表達(dá)式API,也就是說(shuō)你可以使用 <expression>__<transform1>__<transform2>
。
bilateral
New in Django 1.8.
一個(gè)布爾值,表明是否對(duì)lhs
和 rhs
都應(yīng)用這個(gè)轉(zhuǎn)換。如果對(duì)兩側(cè)都應(yīng)用轉(zhuǎn)換,應(yīng)用在rhs
的順序和在查找表達(dá)式中的出現(xiàn)順序相同。默認(rèn)這個(gè)屬性為False
。使用方法的實(shí)例請(qǐng)見(jiàn)自定義查找。
lhs
在左邊,也就是被轉(zhuǎn)換的東西。必須遵循查詢表達(dá)式API。
lookup_name
查找的名稱,用于在解析查詢表達(dá)式的時(shí)候識(shí)別它。
output_field
為這個(gè)類定義轉(zhuǎn)換后的輸出。必須為Field
的實(shí)例。默認(rèn)情況下和lhs.output_field
相同。
as_sql()
需要被覆寫;否則拋出NotImplementedError
異常。
get_lookup(lookup_name)
和get_lookup()
相同。
get_transform(transform_name)
和get_transform()
相同。
class Lookup
Lookup
是實(shí)現(xiàn)查找的通用的類。查找是一個(gè)查詢表達(dá)式,它的左邊是lhs
,右邊是rhs
;lookup_name
用于構(gòu)造lhs
和rhs
之間的比較,來(lái)產(chǎn)生布爾值,例如lhs in rhs
或者lhs > rhs
。
在表達(dá)式中執(zhí)行查找的標(biāo)記是<lhs>__<lookup_name>=<rhs>
。
這個(gè)類并不遵循查詢表達(dá)式API,因?yàn)樵谒鼧?gòu)造的時(shí)候出現(xiàn)了=<rhs>
:查找總是在查找表達(dá)式的最后。
lhs
在左邊,也就是被查找的東西。這個(gè)對(duì)象必須遵循查詢表達(dá)式API。
rhs
在右邊,也就是用來(lái)和lhs
比較的東西。它可以是個(gè)簡(jiǎn)單的值,也可以是在SQL中編譯的一些東西,比如 F()
對(duì)象或者QuerySet
。
lookup_name
查找的名稱,用于在解析查詢表達(dá)式的時(shí)候識(shí)別它。
process_lhs(compiler, connection[, lhs=None])
返回元組(lhs_string, lhs_params)
,和compiler.compile(lhs)
所返回的一樣。這個(gè)方法可以被覆寫,來(lái)調(diào)整lhs
的處理方式。
compiler
是一個(gè)SQLCompiler
對(duì)象,可以像 compiler.compile(lhs)
這樣使用來(lái)編譯lhs
。connection
可以用于編譯供應(yīng)商特定的SQL語(yǔ)句。lhs
如果不為None
, 會(huì)代替self.lhs
作為處理后的lhs
使用。
process_rhs(compiler, connection)
對(duì)于右邊的東西,和process_lhs()
的行為相同。
譯者:Django 文檔協(xié)作翻譯小組,原文:Lookup expressions。
本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請(qǐng)保留作者署名和文章出處。
Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。