查詢 API 參考

本文檔包含查詢的 API 參考,即 Django 用於建構資料庫查詢的 WHERE 子句的 API。若要瞭解如何使用查詢,請參閱建立查詢;若要瞭解如何建立新的查詢,請參閱如何撰寫自訂查詢

查詢 API 有兩個組成部分:一個 RegisterLookupMixin 類別,用於註冊查詢;以及查詢表示式 API,這是一組類別必須實作的方法,才能註冊為查詢。

Django 有兩個遵循查詢表示式 API 的基底類別,所有 Django 內建的查詢都由此衍生

  • Lookup:用於查詢欄位(例如,field_name__exactexact

  • Transform:用於轉換欄位

查詢表示式由三個部分組成

  • 欄位部分(例如,Book.objects.filter(author__best_friends__first_name...));

  • 轉換部分(可省略)(例如,__lower__first3chars__reversed);

  • 查詢(例如,__icontains),若省略,則預設為 __exact

註冊 API

Django 使用 RegisterLookupMixin,為類別提供介面,以在其本身或其實例上註冊查詢。兩個顯著的例子是 Field,所有模型欄位的基底類別;以及 Transform,所有 Django 轉換的基底類別。

class lookups.RegisterLookupMixin

一個在類別上實作查詢 API 的 mixin。

classmethod register_lookup(lookup, lookup_name=None)

在類別或類別實例中註冊新的查詢。例如

DateField.register_lookup(YearExact)
User._meta.get_field("date_joined").register_lookup(MonthExact)

將在 DateField 上註冊 YearExact 查詢,並在 User.date_joined 上註冊 MonthExact 查詢(您可以使用 欄位存取 API 來擷取單個欄位實例)。它會覆寫已存在相同名稱的查詢。在欄位實例上註冊的查詢優先於在類別上註冊的查詢。lookup_name 將用於此查詢(如果提供),否則將使用 lookup.lookup_name

get_lookup(lookup_name)

根據呼叫它的內容,傳回在類別或類別實例中註冊的、名為 lookup_nameLookup。預設實作會遞迴查看所有父類別,並檢查是否有任何父類別有名為 lookup_name 的已註冊查詢,並傳回第一個符合的項目。實例查詢將覆寫任何具有相同 lookup_name 的類別查詢。

get_lookups()

傳回一個字典,其中包含在類別或類別實例中註冊的每個查詢名稱,並對應到 Lookup 類別。

get_transform(transform_name)

傳回在類別或類別實例中註冊的、名為 transform_nameTransform。預設實作會遞迴查看所有父類別,以檢查是否有任何父類別有名為 transform_name 的已註冊轉換,並傳回第一個符合的項目。

若要使類別成為查詢,它必須遵循查詢表示式 APILookupTransform 自然會遵循此 API。

查詢表示式 API

查詢表示式 API 是一組通用的方法,類別會定義這些方法以在查詢表示式中使用,以便將自己轉換為 SQL 表示式。直接欄位參考、聚合和 Transform 都是遵循此 API 的範例。當類別實作以下方法時,表示它遵循查詢表示式 API

as_sql(compiler, connection)

產生表示式的 SQL 片段。傳回一個元組 (sql, params),其中 sql 是 SQL 字串,而 params 是查詢參數的清單或元組。compiler 是一個 SQLCompiler 物件,它有一個 compile() 方法可用於編譯其他表示式。connection 是用於執行查詢的連線。

直接呼叫 expression.as_sql() 通常是不正確的 - 應該使用 compiler.compile(expression) 來代替。compiler.compile() 方法會負責呼叫表示式的特定廠商方法。

如果 as_vendorname() 方法或子類別可能需要提供資料以覆寫 SQL 字串的產生,則可以在此方法上定義自訂關鍵字引數。請參閱Func.as_sql() 以取得範例用法。

as_vendorname(compiler, connection)

其運作方式類似於 as_sql() 方法。當一個表達式被 compiler.compile() 編譯時,Django 會先嘗試呼叫 as_vendorname(),其中 vendorname 是用於執行查詢的後端供應商名稱。對於 Django 的內建後端,vendornamepostgresqloraclesqlitemysql 其中之一。

get_lookup(lookup_name)

必須回傳名為 lookup_name 的查找。例如,可以透過回傳 self.output_field.get_lookup(lookup_name) 來達成。

get_transform(transform_name)

必須回傳名為 transform_name 的轉換。例如,可以透過回傳 self.output_field.get_transform(transform_name) 來達成。

output_field

定義 get_lookup() 方法回傳的類別型別。它必須是一個 Field 實例。

Transform 參考

class Transform[原始碼]

Transform 是一個通用類別,用於實作欄位轉換。一個顯著的範例是 __year,它將 DateField 轉換為 IntegerField

在查找表達式中使用 Transform 的表示法是 <表達式>__<轉換> (例如 date__year)。

此類別遵循 查詢表達式 API,這表示您可以使用 <表達式>__<轉換1>__<轉換2>。它是一個特殊的 Func() 表達式,只接受一個參數。它也可以用於篩選器的右側或直接作為註解。

bilateral

一個布林值,指示此轉換是否應同時套用於 lhsrhs。雙向轉換將以它們在查找表達式中出現的相同順序套用於 rhs。預設情況下,它設定為 False。有關使用範例,請參閱 如何撰寫自訂查找

lhs[原始碼]

左側 - 正在轉換的內容。它必須遵循 查詢表達式 API

lookup_name

查找的名稱,用於在剖析查詢表達式時識別它。它不能包含字串 "__"

output_field

定義此轉換輸出的類別。它必須是一個 Field 實例。預設情況下,與其 lhs.output_field 相同。

Lookup 參考

class Lookup[原始碼]

Lookup 是一個通用類別,用於實作查找。查找是一個查詢表達式,具有左側,lhs;右側,rhs;以及用於產生 lhsrhs 之間布林比較的 lookup_name,例如 lhs in rhslhs > rhs

在表達式中使用查找的主要表示法是 <lhs>__<lookup_name>=<rhs>。查找也可以直接用於 QuerySet 篩選器中

Book.objects.filter(LessThan(F("word_count"), 7500))

…或註解

Book.objects.annotate(is_short_story=LessThan(F("word_count"), 7500))
lhs

左側 - 正在查找的內容。該物件通常遵循 查詢表達式 API。它也可能是一個純值。

rhs

右側 - lhs 正在與之比較的內容。它可以是一個純值,或者可以編譯為 SQL 的內容,通常是一個 F() 物件或一個 QuerySet

lookup_name

此查找的名稱,用於在剖析查詢表達式時識別它。它不能包含字串 "__"

prepare_rhs

預設為 True。當 rhs 是一個純值時,prepare_rhs 決定是否應將其準備為查詢中的參數使用。為了做到這一點,如果已定義,則會呼叫 lhs.output_field.get_prep_value(),否則會將 rhs 包裝在 Value() 中。

process_lhs(compiler, connection, lhs=None)[原始碼]

回傳一個元組 (lhs_string, lhs_params),如同 compiler.compile(lhs) 回傳的結果。可以覆寫此方法以調整如何處理 lhs

compiler 是一個 SQLCompiler 物件,可像 compiler.compile(lhs) 一樣用於編譯 lhsconnection 可用於編譯廠商特定的 SQL。如果 lhs 不是 None,請使用它作為已處理的 lhs,而不是 self.lhs

process_rhs(compiler, connection)[原始碼]

行為與 process_lhs() 相同,用於處理右側 (right-hand side)。

回到頂部