New in Django 1.7.
這篇文檔是查找 API 的參考,Django 用這些API 構(gòu)建數(shù)據(jù)庫(kù)查詢(xún)的WHERE 子句。若要學(xué)習(xí)如何使用 查找,參見(jiàn)執(zhí)行查詢(xún);若要了解如何創(chuàng)建 新的查找,參見(jiàn)自定義查找。
查找 API 由兩個(gè)部分組成:RegisterLookupMixin 類(lèi),它用于注冊(cè)查找;查詢(xún)表達(dá)式API,它是一個(gè)方法集,類(lèi)必須實(shí)現(xiàn)它們才可以注冊(cè)成一個(gè)查找。
Django 有兩個(gè)類(lèi)遵循查詢(xún)表達(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)為類(lèi)提供接口,注冊(cè)它自己的查找。兩個(gè)最突出的例子是Field(所有模型字段的基類(lèi))和 Aggregate(Django 所有聚合函數(shù)的基類(lèi))。
class lookups.RegisterLookupMixin
一個(gè)mixin,實(shí)現(xiàn)一個(gè)類(lèi)上的查找API。
classmethod register_lookup(lookup)
在類(lèi)中注冊(cè)一個(gè)新的查找。例如,DateField.register_lookup(YearExact) 將在DateField上注冊(cè)一個(gè) YearExact查找。它會(huì)覆蓋已存在的同名查找。
get_lookup(lookup_name)
返回類(lèi)中注冊(cè)的名為lookup_name 的 Lookup。默認(rèn)的實(shí)現(xiàn)會(huì)遞歸查詢(xún)所有的父類(lèi),并檢查它們中的任何一個(gè)是否具有名稱(chēng)為lookup_name的查找,并返回第一個(gè)匹配。
get_transform(transform_name)
返回一個(gè)名為transform_name 的Transform。默認(rèn)的實(shí)現(xiàn)會(huì)遞歸查找所有的父類(lèi),并檢查它們中的任何一個(gè)是否具有名稱(chēng)為transform_name的查找,并返回第一個(gè)匹配。
一個(gè)類(lèi)如果想要成為查找,它必須實(shí)現(xiàn)查詢(xún)表達(dá)式API。Lookup 和Transform一開(kāi)始就遵循這個(gè)API。
查詢(xún)表達(dá)式API是一個(gè)通用的方法集,在查詢(xún)表達(dá)式中可以使用定義了這些方法的類(lèi),來(lái)將它們自身轉(zhuǎn)換為SQL表達(dá)式。直接的字段引用,聚合,以及Transform類(lèi)都是遵循這個(gè)API的示例。當(dāng)一個(gè)對(duì)象實(shí)現(xiàn)以下方法時(shí),就被稱(chēng)為遵循查詢(xún)表達(dá)式API:
as_sql(self, compiler, connection)
負(fù)責(zé)從表達(dá)式中產(chǎn)生查詢(xún)字符串和參數(shù)。compiler是一個(gè)SQLCompiler對(duì)象,它擁有可以編譯其它表達(dá)式的compile()方法。connection是用于執(zhí)行查詢(xún)的連接。
調(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()的工作方式類(lèi)似。當(dāng)一個(gè)表達(dá)式經(jīng)過(guò)compiler.compile()編譯之后, Django會(huì)首先嘗試調(diào)用as_vendorname(),其中vendorname是用于執(zhí)行查詢(xún)的后端供應(yīng)商。對(duì)于Django內(nèi)建的后端,vendorname是postgresql,oracle,sqlite,或者mysql之一。
get_lookup(lookup_name)
必須返回名稱(chēng)為lookup_name的查找。例如,通過(guò)返回self.output_field.get_lookup(lookup_name)來(lái)實(shí)現(xiàn)。
get_transform(transform_name)
必須返回名稱(chēng)為transform_name的查找。例如,通過(guò)返回self.output_field.get_transform(transform_name)來(lái)實(shí)現(xiàn)。
output_field
定義get_lookup()方法所返回的類(lèi)的類(lèi)型。必須為Field的實(shí)例。
class Transform
Transform是用于實(shí)現(xiàn)字段轉(zhuǎn)換的通用類(lèi)。一個(gè)顯然的例子是__year會(huì)把DateField轉(zhuǎn)換為IntegerField。
在表達(dá)式中執(zhí)行查找的標(biāo)記是Transform<expression>__<transformation> (例如 date__year)。
這個(gè)類(lèi)遵循查詢(xún)表達(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)換的東西。必須遵循查詢(xún)表達(dá)式API。
lookup_name
查找的名稱(chēng),用于在解析查詢(xún)表達(dá)式的時(shí)候識(shí)別它。
output_field
為這個(gè)類(lèi)定義轉(zhuǎn)換后的輸出。必須為Field的實(shí)例。默認(rèn)情況下和lhs.output_field相同。
as_sql()
需要被覆寫(xiě);否則拋出NotImplementedError異常。
get_lookup(lookup_name)
和get_lookup()相同。
get_transform(transform_name)
和get_transform()相同。
class Lookup
Lookup是實(shí)現(xiàn)查找的通用的類(lèi)。查找是一個(gè)查詢(xún)表達(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è)類(lèi)并不遵循查詢(xún)表達(dá)式API,因?yàn)樵谒鼧?gòu)造的時(shí)候出現(xiàn)了=<rhs>:查找總是在查找表達(dá)式的最后。
lhs
在左邊,也就是被查找的東西。這個(gè)對(duì)象必須遵循查詢(xún)表達(dá)式API。
rhs
在右邊,也就是用來(lái)和lhs比較的東西。它可以是個(gè)簡(jiǎn)單的值,也可以是在SQL中編譯的一些東西,比如 F() 對(duì)象或者QuerySet。
lookup_name
查找的名稱(chēng),用于在解析查詢(xún)表達(dá)式的時(shí)候識(shí)別它。
process_lhs(compiler, connection[, lhs=None])
返回元組(lhs_string, lhs_params),和compiler.compile(lhs)所返回的一樣。這個(gè)方法可以被覆寫(xiě),來(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。