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