執行原生查詢
Manager.raw(raw_query, params=None, translations=None)
raw_query:執行的sql語句
params:需要格式化的參數,類型:清單
translations:值為字典,将查出來的資料鍵值對化,根據模型屬性聲明查詢出來的鍵,如:{模型屬性:鍵}
模型
class Person(models.Model):
first_name = models.CharField(...)
last_name = models.CharField(...)
birth_date = models.DateField(...)
然後你可以像這樣執行自定義 SQL:
>>> for p in Person.objects.raw('SELECT * FROM myapp_person'):
... print(p)
John Smith
Jane Jones
我們還可以這樣讓sql語句更有閱讀性
>>> Person.objects.raw('''SELECT first AS first_name,
... last AS last_name,
... bd AS birth_date,
... pk AS id,
... FROM some_other_table''')
這個例子并不令人興奮——實際上,這就是運作 Person.objects.all()。然而, raw() 有很多額外選項,使得它非常強大。比如省略字段,支援索引
或者,你可以用 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()
如果你需要執行參數化的查詢,可以使用 raw() 的 params 參數:
lname = 'Doe'
#下面這種方式可以防止sql注入
Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])
#下面這種方式存在隐患,可以被sql注入
Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s' %lname)
直接執行自定義 SQL
有時候,甚至 Manager.raw() 都無法滿足需求:你可能要執行不明确映射至模型的查詢語句,或者就是直接執行 UPDATE, INSERT 或 DELETE 語句。
這些情況下,你總是能直接通路資料庫,完全繞過模型層。
對象 django.db.connection 代表預設資料庫連接配接。要使用這個資料庫連接配接,調用 connection.cursor() 來擷取一個指針對象。然後,調用 cursor.execute(sql, [params]) 來執行該 SQL 和 cursor.fetchone(),或 cursor.fetchall() 擷取結果資料。
例如:
from django.db import connection
def my_custom_sql(self):
with connection.cursor() as cursor:
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
row = cursor.fetchone()
return row
若你同時使用 不止一個資料庫,你可以使用 django.db.connections 擷取指定資料庫的連接配接(和指針)。 django.db.connections 是一個類字典對象,它允許你通過連接配接别名擷取指定連接配接:
from django.db import connections
with connections['my_db_alias'].cursor() as cursor:
# 邏輯代碼
三種查詢方法的輸出類型
>>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2");
>>> cursor.fetchall()
((54360982, None), (54360880, None))
>>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2");
>>> dictfetchall(cursor)
[{'parent_id': None, 'id': 54360982}, {'parent_id': None, 'id': 54360880}]
>>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2");
>>> results = namedtuplefetchall(cursor)
>>> results
[Result(id=54360982, parent_id=None), Result(id=54360880, parent_id=None)]
>>> results[0].id
54360982
>>> results[0][0]
54360982