# 查找 API 參考 #
```
New in Django 1.7.
```
這篇文檔是查找 API 的參考,Django 用這些API 構建數據庫查詢的`WHERE` 子句。若要學習如何使用 查找,參見[執行查詢](http://python.usyiyi.cn/django/topics/db/queries.html);若要了解如何創建 新的查找,參見[自定義查找](http://python.usyiyi.cn/django/howto/custom-lookups.html)。
查找 API 由兩個部分組成:`RegisterLookupMixin` 類,它用于注冊查找;[查詢表達式API](http://python.usyiyi.cn/django/ref/models/lookups.html#query-expression),它是一個方法集,類必須實現它們才可以注冊成一個查找。
Django 有兩個類遵循查詢表達式API,且Django 所有內建的查找都繼承自它們:
+ `Lookup`:用于查找一個字段(例如`field_name__exact` 中的`exact`)
+ `Transform`:用于轉換一個字段
查找表達式由三部分組成:
+ 字段部分(例如, `Book.objects.filter(author__best_friends__first_name...)`;
+ 轉換部分(可以省略)(例如, `__lower__first3chars__reversed`);
+ 查找部分(例如,`__icontains`),如果省略則默認為`__exact`。
## 注冊 API ##
Django 使用`RegisterLookupMixin` 來為類提供接口,注冊它自己的查找。兩個最突出的例子是`Field`(所有模型字段的基類)和 `Aggregate`(Django 所有聚合函數的基類)。
`class lookups.RegisterLookupMixin`
一個mixin,實現一個類上的查找API。
`classmethod register_lookup(lookup)`
在類中注冊一個新的查找。例如,`DateField.register_lookup(YearExact)` 將在`DateField `上注冊一個 `YearExact`查找。它會覆蓋已存在的同名查找。
`get_lookup(lookup_name)`
返回類中注冊的名為`lookup_name` 的 `Lookup`。默認的實現會遞歸查詢所有的父類,并檢查它們中的任何一個是否具有名稱為`lookup_name`的查找,并返回第一個匹配。
`get_transform(transform_name)`
返回一個名為`transform_name` 的`Transform`。默認的實現會遞歸查找所有的父類,并檢查它們中的任何一個是否具有名稱為`transform_name`的查找,并返回第一個匹配。
一個類如果想要成為查找,它必須實現查詢表達式API。`Lookup` 和`Transform`一開始就遵循這個API。
## 查詢表達式API ##
查詢表達式API是一個通用的方法集,在查詢表達式中可以使用定義了這些方法的類,來將它們自身轉換為SQL表達式。直接的字段引用,聚合,以及`Transform`類都是遵循這個API的示例。當一個對象實現以下方法時,就被稱為遵循查詢表達式API:
`as_sql(self, compiler, connection)`
負責從表達式中產生查詢字符串和參數。`compiler`是一個`SQLCompiler`對象,它擁有可以編譯其它表達式的`compile()`方法。`connection`是用于執行查詢的連接。
調用`expression.as_sql()`一般是不對的 -- 而是應該調用`compiler.compile(expression)`。 `compiler.compile()`方法應該在調用表達式的供應商特定方法時格外小心。
`as_vendorname(self, compiler, connection)`
和`as_sql()`的工作方式類似。當一個表達式經過`compiler.compile()`編譯之后, Django會首先嘗試調用`as_vendorname()`,其中`vendorname`是用于執行查詢的后端供應商。對于Django內建的后端,`vendorname`是`postgresql`,`oracle`,`sqlite`,或者`mysql`之一。
`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<expression>__<transformation>` (例如 `date__year`)。
這個類遵循查詢表達式API,也就是說你可以使用 `<expression>__<transform1>__<transform2>`。
`bilateral`
```
New in Django 1.8.
```
一個布爾值,表明是否對`lhs`和 `rhs`都應用這個轉換。如果對兩側都應用轉換,應用在`rhs`的順序和在查找表達式中的出現順序相同。默認這個屬性為`False`。使用方法的實例請見自定義查找。
`lhs`
在左邊,也就是被轉換的東西。必須遵循查詢表達式API。
`lookup_name`
查找的名稱,用于在解析查詢表達式的時候識別它。
`output_field`
為這個類定義轉換后的輸出。必須為`Field`的實例。默認情況下和`lhs.output_field`相同。
`as_sql()`
需要被覆寫;否則拋出`NotImplementedError`異常。
`get_lookup(lookup_name)`
和`get_lookup()`相同。
`get_transform(transform_name)`
和`get_transform()`相同。
## Lookup 類參考 ##
`class Lookup`
`Lookup`是實現查找的通用的類。查找是一個查詢表達式,它的左邊是`lhs`,右邊是`rhs`;`lookup_name`用于構造`lhs`和`rhs`之間的比較,來產生布爾值,例如`lhs in rhs`或者`lhs > rhs`。
在表達式中執行查找的標記是`<lhs>__<lookup_name>=<rhs>`。
這個類并不遵循查詢表達式API,因為在它構造的時候出現了`=<rhs>`:查找總是在查找表達式的最后。
`lhs`
在左邊,也就是被查找的東西。這個對象必須遵循查詢表達式API。
`rhs`
在右邊,也就是用來和`lhs`比較的東西。它可以是個簡單的值,也可以是在SQL中編譯的一些東西,比如 `F()` 對象或者`QuerySet`。
`lookup_name`
查找的名稱,用于在解析查詢表達式的時候識別它。
`process_lhs(compiler, connection[, lhs=None])`
返回元組`(lhs_string, lhs_params)`,和`compiler.compile(lhs)`所返回的一樣。這個方法可以被覆寫,來調整`lhs`的處理方式。
`compiler`是一個`SQLCompiler`對象,可以像 `compiler.compile(lhs)`這樣使用來編譯`lhs`。`connection`可以用于編譯供應商特定的SQL語句。`lhs`如果不為`None`, 會代替`self.lhs`作為處理后的`lhs`使用。
`process_rhs(compiler, connection)`
對于右邊的東西,和`process_lhs()`的行為相同。
> 譯者:[Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html),原文:[Lookup expressions](https://docs.djangoproject.com/en/1.8/ref/models/lookups/)。
>
> 本文以 [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 協議發布,轉載請保留作者署名和文章出處。
>
> [Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html)人手緊缺,有興趣的朋友可以加入我們,完全公益性質。交流群:467338606。
- 新手入門
- 從零開始
- 概覽
- 安裝
- 教程
- 第1部分:模型
- 第2部分:管理站點
- 第3部分:視圖和模板
- 第4部分:表單和通用視圖
- 第5部分:測試
- 第6部分:靜態文件
- 高級教程
- 如何編寫可重用的應用
- 為Django編寫首個補丁
- 模型層
- 模型
- 模型語法
- 元選項
- 模型類
- 查詢集
- 執行查詢
- 查找表達式
- 模型的實例
- 實例方法
- 訪問關聯對象
- 遷移
- 模式編輯器
- 編寫遷移
- 高級
- 管理器
- 原始的SQL查詢
- 聚合
- 多數據庫
- 自定義查找
- 條件表達式
- 數據庫函數
- 其它
- 遺留的數據庫
- 提供初始數據
- 優化數據庫訪問
- 視圖層
- 基礎
- URL配置
- 視圖函數
- 快捷函數
- 裝飾器
- 參考
- 內建的視圖
- TemplateResponse 對象
- 文件上傳
- 概覽
- File 對象
- 儲存API
- 管理文件
- 自定義存儲
- 基于類的視圖
- 概覽
- 內建顯示視圖
- 內建編輯視圖
- API參考
- 分類索引
- 高級
- 生成 CSV
- 生成 PDF
- 中間件
- 概覽
- 內建的中間件類
- 模板層
- 基礎
- 面向設計師
- 語言概覽
- 人性化
- 面向程序員
- 表單
- 基礎
- 概覽
- 表單API
- 內建的Widget
- 高級
- 整合媒體
- 開發過程
- 設置
- 概覽
- 應用程序
- 異常
- 概覽
- django-admin 和 manage.py
- 添加自定義的命令
- 測試
- 介紹
- 部署
- 概述
- WSGI服務器
- 部署靜態文件
- 通過email追蹤代碼錯誤
- Admin
- 管理操作
- 管理文檔生成器
- 安全
- 安全概述
- 說明Django中的安全問題
- 點擊劫持保護
- 加密簽名
- 國際化和本地化
- 概述
- 本地化WEB UI格式化輸入
- “本地特色”
- 常見的網站應用工具
- 認證
- 概覽
- 使用認證系統
- 密碼管理
- 日志
- 分頁
- 會話
- 數據驗證
- 其它核心功能
- 按需內容處理
- 重定向
- 信號
- 系統檢查框架