在Django中如何執(zhí)行原生SQL查詢?cè)斀?/h1>
更新時(shí)間:2025年10月21日 10:02:18 作者:唐古烏梁海
Django框架作為Python中一個(gè)強(qiáng)大的Web開發(fā)框架,提供了豐富的ORM功能,使得開發(fā)者能夠通過Python對(duì)象來操作數(shù)據(jù)庫(kù),這篇文章主要介紹了在Django中如何執(zhí)行原生SQL查詢的相關(guān)資料,需要的朋友可以參考下
在Django中,執(zhí)行原生SQL查詢
1. 使用raw()方法
raw() 方法允許你執(zhí)行原生SQL查詢并返回模型實(shí)例:
from myapp.models import Person
# 基本查詢
people = Person.objects.raw('SELECT * FROM myapp_person WHERE age > %s', [18])
# 遍歷結(jié)果
for person in people:
print(person.name, person.age)
# 帶參數(shù)的查詢
people = Person.objects.raw(
'SELECT * FROM myapp_person WHERE age BETWEEN %s AND %s',
[20, 30]
)
2. 使用數(shù)據(jù)庫(kù)連接直接執(zhí)行SQL
基本用法:
from django.db import connection
def my_custom_sql():
with connection.cursor() as cursor:
# 執(zhí)行查詢
cursor.execute("SELECT * FROM myapp_person WHERE age > %s", [25])
# 獲取所有結(jié)果
rows = cursor.fetchall()
# 或者逐行獲取
# row = cursor.fetchone()
# rows = cursor.fetchmany(size=10)
return rows
返回字典格式的結(jié)果:
from django.db import connection
def dictfetchall(cursor):
"""將游標(biāo)結(jié)果轉(zhuǎn)換為字典列表"""
columns = [col[0] for col in cursor.description]
return [
dict(zip(columns, row))
for row in cursor.fetchall()
]
def my_custom_sql():
with connection.cursor() as cursor:
cursor.execute("SELECT id, name, age FROM myapp_person")
results = dictfetchall(cursor)
return results
3. 使用多個(gè)數(shù)據(jù)庫(kù)
如果你的項(xiàng)目配置了多個(gè)數(shù)據(jù)庫(kù):
from django.db import connections
def query_multiple_dbs():
# 使用默認(rèn)數(shù)據(jù)庫(kù)
with connections['default'].cursor() as cursor:
cursor.execute("SELECT * FROM table1")
# 處理結(jié)果
# 使用其他數(shù)據(jù)庫(kù)
with connections['other_db'].cursor() as cursor:
cursor.execute("SELECT * FROM table2")
# 處理結(jié)果
4. 執(zhí)行寫操作(INSERT/UPDATE/DELETE)
from django.db import connection
def update_data():
with connection.cursor() as cursor:
# INSERT
cursor.execute(
"INSERT INTO myapp_person (name, age) VALUES (%s, %s)",
['John', 30]
)
# UPDATE
cursor.execute(
"UPDATE myapp_person SET age = %s WHERE name = %s",
[31, 'John']
)
# DELETE
cursor.execute(
"DELETE FROM myapp_person WHERE age < %s",
[18]
)
5. 事務(wù)處理
from django.db import transaction, connection
@transaction.atomic
def complex_operation():
with connection.cursor() as cursor:
try:
# 一系列SQL操作
cursor.execute("UPDATE accounts SET balance = balance - %s", [100])
cursor.execute("UPDATE accounts SET balance = balance + %s", [100])
except Exception as e:
# 出錯(cuò)時(shí)會(huì)自動(dòng)回滾
print(f"Error: {e}")
6. 實(shí)用的封裝函數(shù)
from django.db import connection
def execute_query(query, params=None, return_dict=True):
"""
執(zhí)行SQL查詢的通用函數(shù)
"""
with connection.cursor() as cursor:
cursor.execute(query, params or [])
if query.strip().upper().startswith('SELECT'):
if return_dict:
columns = [col[0] for col in cursor.description]
return [dict(zip(columns, row)) for row in cursor.fetchall()]
else:
return cursor.fetchall()
else:
# 對(duì)于非SELECT查詢,返回受影響的行數(shù)
return cursor.rowcount
# 使用示例
results = execute_query(
"SELECT name, age FROM myapp_person WHERE age > %s",
[25]
)

注意事項(xiàng)
SQL注入防護(hù):始終使用參數(shù)化查詢,不要直接拼接字符串
# ? 安全:使用參數(shù)化查詢
cursor.execute("SELECT * FROM users WHERE username = %s", [username])
# ? 危險(xiǎn):字符串拼接(SQL注入風(fēng)險(xiǎn))
cursor.execute(f"SELECT * FROM users WHERE username = '{username}'")
# ? 危險(xiǎn):直接傳遞用戶輸入
cursor.execute("SELECT * FROM users WHERE username = %s" % username)
表名引用:在SQL中使用實(shí)際的數(shù)據(jù)庫(kù)表名,而不是模型名
性能考慮:原生SQL通常更快,但失去了Django ORM的一些便利功能;使用直接連接:需要最高性能、復(fù)雜查詢或跨表查詢
數(shù)據(jù)庫(kù)兼容性:如果你使用多個(gè)數(shù)據(jù)庫(kù)后端,要注意SQL語(yǔ)法的差異
這些方法讓你在需要優(yōu)化性能或執(zhí)行復(fù)雜查詢時(shí),能夠靈活地使用原生SQL,同時(shí)保持代碼的安全性和可維護(hù)性。
總結(jié)
到此這篇關(guān)于在Django中如何執(zhí)行原生SQL查詢的文章就介紹到這了,更多相關(guān)Django執(zhí)行原生SQL查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
-
Python實(shí)現(xiàn)獲取照片拍攝日期并重命名的方法
這篇文章主要介紹了Python實(shí)現(xiàn)獲取照片拍攝日期并重命名的方法,涉及Python針對(duì)文件屬性及文件名相關(guān)操作技巧,需要的朋友可以參考下 2017-09-09
-
pytorch加載自己的圖片數(shù)據(jù)集的2種方法詳解
數(shù)據(jù)預(yù)處理在解決深度學(xué)習(xí)問題的過程中,往往需要花費(fèi)大量的時(shí)間和精力,下面這篇文章主要給大家介紹了關(guān)于pytorch加載自己的圖片數(shù)據(jù)集的2種方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下 2022-06-06
-
選擇Python寫網(wǎng)絡(luò)爬蟲的優(yōu)勢(shì)和理由
在本篇文章里小編給各位整理了一篇關(guān)于選擇Python寫網(wǎng)絡(luò)爬蟲的優(yōu)勢(shì)和理由以及相關(guān)代碼實(shí)例,有興趣的朋友們閱讀下吧。 2019-07-07
-
Python+OpenCV實(shí)戰(zhàn)之利用?K-Means?聚類進(jìn)行色彩量化
這篇文章主要介紹了如何利用?K-Means?聚類進(jìn)行色彩量化,以減少圖像中顏色數(shù)量。文中的代碼具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以關(guān)注一下 2021-12-12
-
Python如何將bmp格式的圖片批量轉(zhuǎn)成jpg
這篇文章主要介紹了Python如何將bmp格式的圖片批量轉(zhuǎn)成jpg問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教 2023-03-03
-
Python可視化學(xué)習(xí)之seaborn繪制矩陣圖詳解
矩陣圖即用一張圖繪制多個(gè)變量之間的關(guān)系,數(shù)據(jù)挖掘中常用于初期數(shù)據(jù)探索。本文介紹python中seaborn.pairplot和seaborn.PairGrid繪制矩陣圖,需要的可以參考一下 2022-02-02
-
簡(jiǎn)單了解python gevent 協(xié)程使用及作用
這篇文章主要介紹了簡(jiǎn)單了解python gevent 協(xié)程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下 2019-07-07
-
Python連接Hadoop數(shù)據(jù)中遇到的各種坑(匯總)
這篇文章主要介紹了Python連接Hadoop數(shù)據(jù)中遇到的各種坑,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧 2020-04-04
最新評(píng)論
在Django中,執(zhí)行原生SQL查詢
1. 使用raw()方法
raw() 方法允許你執(zhí)行原生SQL查詢并返回模型實(shí)例:
from myapp.models import Person
# 基本查詢
people = Person.objects.raw('SELECT * FROM myapp_person WHERE age > %s', [18])
# 遍歷結(jié)果
for person in people:
print(person.name, person.age)
# 帶參數(shù)的查詢
people = Person.objects.raw(
'SELECT * FROM myapp_person WHERE age BETWEEN %s AND %s',
[20, 30]
)
2. 使用數(shù)據(jù)庫(kù)連接直接執(zhí)行SQL
基本用法:
from django.db import connection
def my_custom_sql():
with connection.cursor() as cursor:
# 執(zhí)行查詢
cursor.execute("SELECT * FROM myapp_person WHERE age > %s", [25])
# 獲取所有結(jié)果
rows = cursor.fetchall()
# 或者逐行獲取
# row = cursor.fetchone()
# rows = cursor.fetchmany(size=10)
return rows
返回字典格式的結(jié)果:
from django.db import connection
def dictfetchall(cursor):
"""將游標(biāo)結(jié)果轉(zhuǎn)換為字典列表"""
columns = [col[0] for col in cursor.description]
return [
dict(zip(columns, row))
for row in cursor.fetchall()
]
def my_custom_sql():
with connection.cursor() as cursor:
cursor.execute("SELECT id, name, age FROM myapp_person")
results = dictfetchall(cursor)
return results
3. 使用多個(gè)數(shù)據(jù)庫(kù)
如果你的項(xiàng)目配置了多個(gè)數(shù)據(jù)庫(kù):
from django.db import connections
def query_multiple_dbs():
# 使用默認(rèn)數(shù)據(jù)庫(kù)
with connections['default'].cursor() as cursor:
cursor.execute("SELECT * FROM table1")
# 處理結(jié)果
# 使用其他數(shù)據(jù)庫(kù)
with connections['other_db'].cursor() as cursor:
cursor.execute("SELECT * FROM table2")
# 處理結(jié)果
4. 執(zhí)行寫操作(INSERT/UPDATE/DELETE)
from django.db import connection
def update_data():
with connection.cursor() as cursor:
# INSERT
cursor.execute(
"INSERT INTO myapp_person (name, age) VALUES (%s, %s)",
['John', 30]
)
# UPDATE
cursor.execute(
"UPDATE myapp_person SET age = %s WHERE name = %s",
[31, 'John']
)
# DELETE
cursor.execute(
"DELETE FROM myapp_person WHERE age < %s",
[18]
)
5. 事務(wù)處理
from django.db import transaction, connection
@transaction.atomic
def complex_operation():
with connection.cursor() as cursor:
try:
# 一系列SQL操作
cursor.execute("UPDATE accounts SET balance = balance - %s", [100])
cursor.execute("UPDATE accounts SET balance = balance + %s", [100])
except Exception as e:
# 出錯(cuò)時(shí)會(huì)自動(dòng)回滾
print(f"Error: {e}")
6. 實(shí)用的封裝函數(shù)
from django.db import connection
def execute_query(query, params=None, return_dict=True):
"""
執(zhí)行SQL查詢的通用函數(shù)
"""
with connection.cursor() as cursor:
cursor.execute(query, params or [])
if query.strip().upper().startswith('SELECT'):
if return_dict:
columns = [col[0] for col in cursor.description]
return [dict(zip(columns, row)) for row in cursor.fetchall()]
else:
return cursor.fetchall()
else:
# 對(duì)于非SELECT查詢,返回受影響的行數(shù)
return cursor.rowcount
# 使用示例
results = execute_query(
"SELECT name, age FROM myapp_person WHERE age > %s",
[25]
)

注意事項(xiàng)
SQL注入防護(hù):始終使用參數(shù)化查詢,不要直接拼接字符串
# ? 安全:使用參數(shù)化查詢 cursor.execute("SELECT * FROM users WHERE username = %s", [username]) # ? 危險(xiǎn):字符串拼接(SQL注入風(fēng)險(xiǎn)) cursor.execute(f"SELECT * FROM users WHERE username = '{username}'") # ? 危險(xiǎn):直接傳遞用戶輸入 cursor.execute("SELECT * FROM users WHERE username = %s" % username)表名引用:在SQL中使用實(shí)際的數(shù)據(jù)庫(kù)表名,而不是模型名
性能考慮:原生SQL通常更快,但失去了Django ORM的一些便利功能;使用直接連接:需要最高性能、復(fù)雜查詢或跨表查詢
數(shù)據(jù)庫(kù)兼容性:如果你使用多個(gè)數(shù)據(jù)庫(kù)后端,要注意SQL語(yǔ)法的差異
這些方法讓你在需要優(yōu)化性能或執(zhí)行復(fù)雜查詢時(shí),能夠靈活地使用原生SQL,同時(shí)保持代碼的安全性和可維護(hù)性。
總結(jié)
到此這篇關(guān)于在Django中如何執(zhí)行原生SQL查詢的文章就介紹到這了,更多相關(guān)Django執(zhí)行原生SQL查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實(shí)現(xiàn)獲取照片拍攝日期并重命名的方法
這篇文章主要介紹了Python實(shí)現(xiàn)獲取照片拍攝日期并重命名的方法,涉及Python針對(duì)文件屬性及文件名相關(guān)操作技巧,需要的朋友可以參考下2017-09-09
pytorch加載自己的圖片數(shù)據(jù)集的2種方法詳解
數(shù)據(jù)預(yù)處理在解決深度學(xué)習(xí)問題的過程中,往往需要花費(fèi)大量的時(shí)間和精力,下面這篇文章主要給大家介紹了關(guān)于pytorch加載自己的圖片數(shù)據(jù)集的2種方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
選擇Python寫網(wǎng)絡(luò)爬蟲的優(yōu)勢(shì)和理由
在本篇文章里小編給各位整理了一篇關(guān)于選擇Python寫網(wǎng)絡(luò)爬蟲的優(yōu)勢(shì)和理由以及相關(guān)代碼實(shí)例,有興趣的朋友們閱讀下吧。2019-07-07
Python+OpenCV實(shí)戰(zhàn)之利用?K-Means?聚類進(jìn)行色彩量化
這篇文章主要介紹了如何利用?K-Means?聚類進(jìn)行色彩量化,以減少圖像中顏色數(shù)量。文中的代碼具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以關(guān)注一下2021-12-12
Python如何將bmp格式的圖片批量轉(zhuǎn)成jpg
這篇文章主要介紹了Python如何將bmp格式的圖片批量轉(zhuǎn)成jpg問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
Python可視化學(xué)習(xí)之seaborn繪制矩陣圖詳解
矩陣圖即用一張圖繪制多個(gè)變量之間的關(guān)系,數(shù)據(jù)挖掘中常用于初期數(shù)據(jù)探索。本文介紹python中seaborn.pairplot和seaborn.PairGrid繪制矩陣圖,需要的可以參考一下2022-02-02
簡(jiǎn)單了解python gevent 協(xié)程使用及作用
這篇文章主要介紹了簡(jiǎn)單了解python gevent 協(xié)程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
Python連接Hadoop數(shù)據(jù)中遇到的各種坑(匯總)
這篇文章主要介紹了Python連接Hadoop數(shù)據(jù)中遇到的各種坑,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04

