W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
若管理器方法 ?raw()
? 能用于執(zhí)行原生 SQL 查詢,就會返回模型實例:
?Manager.raw(raw_query, params=(), translations=None)
?
該方法接受一個原生 SQL 查詢語句,執(zhí)行它,并返回一個 ?django.db.models.query.RawQuerySet
? 實例。這個 ?RawQuerySet
?能像普通的 ?QuerySet
?一樣被迭代獲取對象實例。
最好用例子來解釋。假設你有以下模型:
class Person(models.Model):
first_name = models.CharField(...)
last_name = models.CharField(...)
birth_date = models.DateField(...)
然后你可以像這樣執(zhí)行自定義 SQL:
>>> for p in Person.objects.raw('SELECT * FROM myapp_person'):
... print(p)
John Smith
Jane Jones
?raw()
? 字段將查詢語句中的字段映射至模型中的字段。
查詢語句中的字段排序并不重要。換而言之,以下兩種查詢是一致的:
>>> Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person')
...
>>> Person.objects.raw('SELECT last_name, birth_date, first_name, id FROM myapp_person')
...
匹配是根據名字來的。這意味著你可以使用 SQL 的 ?AS
?子句將查詢語句中的字段映射至模型中的字段。所以,若你還有一些數據表包含了 ?Person
?數據,你可以很方便的將其映射至 ?Person
?實例:
>>> Person.objects.raw('''SELECT first AS first_name,
... last AS last_name,
... bd AS birth_date,
... pk AS id,
... FROM some_other_table''')
只要名字對上了,模型實例就會被正確創(chuàng)建。
或者,你可以用 ?raw()
? 的 ?translations
?參數將查詢語句中的字段映射至模型中的字段。這是一個字典,將查詢語句中的字段名映射至模型中的字段名。例如,上面的查詢也能這樣寫:
>>> name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
>>> Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
?raw()
? 支持索引,所以,若你只需要第一個結果就這樣寫:
>>> first_person = Person.objects.raw('SELECT * FROM myapp_person')[0]
不過,索引和切片不是在數據庫層面上實現的。若數據庫中有非常多的 Person 對象,可以在 SQL 層面使用 limit 子句:
>>> first_person = Person.objects.raw('SELECT * FROM myapp_person LIMIT 1')[0]
也可以省略字段:
>>> people = Person.objects.raw('SELECT id, first_name FROM myapp_person')
該查詢返回的 Person 對象即延遲模型實例。這意味著查詢語句中省略的字段按需加載。例子:
>>> for p in Person.objects.raw('SELECT id, first_name FROM myapp_person'):
... print(p.first_name, # This will be retrieved by the original query
... p.last_name) # This will be retrieved on demand
...
John Smith
Jane Jones
表面上,看起來該查詢同時檢出了 ?first name
? 和 ?last name
?。然而,這個例子實際上執(zhí)行了三次查詢。只有 ?first names
? 是由 ?raw()
? 查詢檢出的 —— ?last names
? 是在它們被打印時按需檢出。
只有一個字段你不能省略 —— 主鍵字段。Django 用主鍵來區(qū)分模型實例,所以必須在原生查詢語句中包含主鍵。若你忘了包含主鍵會拋出 ?FieldDoesNotExist
? 異常。
你可以執(zhí)行帶有模型中未定義字段的查詢語句。例如,我們能用 PostgreSQL 的 ?age()
? 函數 獲取用戶列表,他們的年齡已由數據庫計算:
>>> people = Person.objects.raw('SELECT *, age(birth_date) AS age FROM myapp_person')
>>> for p in people:
... print("%s is %s." % (p.first_name, p.age))
John is 37.
Jane is 42.
...
如果你需要執(zhí)行參數化的查詢,可以使用 ?raw()
? 的 ?params
?參數:
>>> lname = 'Doe'
>>> Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])
?params
?是一個參數字典。你將用一個列表替換查詢字符串中 ?%s
? 占位符,或用字典替換 ?%(key)s
? 占位符(?key
?被字典 ?key
?替換),不論你使用哪個數據庫引擎。這些占位符會被 ?params
?參數的值替換。
臨時將上述查詢寫作:
>>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname
>>> Person.objects.raw(query)
你可能認為你需要將查詢寫成這樣(用單引號包裹 %s):
>>> query = "SELECT * FROM myapp_person WHERE last_name = '%s'"
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯系方式:
更多建議: