当前位置: 首页 > news >正文

【python】在Django中,执行原生SQL查询 - 指南

文章目录

  • 在Django中,执行原生SQL查询
    • 1. 使用 `raw()` 方法
    • 2. 使用数据库连接直接执行SQL
      • 基本用法:
      • 返回字典格式的结果:
    • 3. 使用多个数据库
    • 4. 执行写操作(INSERT/UPDATE/DELETE)
    • 5. 事务处理
    • 6. 实用的封装函数
    • 注意事项

在Django中,执行原生SQL查询

1. 使用 raw() 方法

raw() 方法允许你执行原生SQL查询并返回模型实例:

from myapp.models import Person
# 基本查询
people = Person.objects.raw('SELECT * FROM myapp_person WHERE age > %s', [18])
# 遍历结果
for person in people:
print(person.name, person.age)
# 带参数的查询
people = Person.objects.raw(
'SELECT * FROM myapp_person WHERE age BETWEEN %s AND %s',
[20, 30]
)

2. 使用数据库连接直接执行SQL

基本用法:

from django.db import connection
def my_custom_sql():
with connection.cursor() as cursor:
# 执行查询
cursor.execute("SELECT * FROM myapp_person WHERE age > %s", [25])
# 获取所有结果
rows = cursor.fetchall()
# 或者逐行获取
# row = cursor.fetchone()
# rows = cursor.fetchmany(size=10)
return rows

返回字典格式的结果:

from django.db import connection
def dictfetchall(cursor):
"""将游标结果转换为字典列表"""
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. 使用多个数据库

如果你的项目配置了多个数据库:

from django.db import connections
def query_multiple_dbs():
# 使用默认数据库
with connections['default'].cursor() as cursor:
cursor.execute("SELECT * FROM table1")
# 处理结果
# 使用其他数据库
with connections['other_db'].cursor() as cursor:
cursor.execute("SELECT * FROM table2")
# 处理结果

4. 执行写操作(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. 事务处理

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:
# 出错时会自动回滚
print(f"Error: {e}")

6. 实用的封装函数

from django.db import connection
def execute_query(query, params=None, return_dict=True):
"""
执行SQL查询的通用函数
"""
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:
# 对于非SELECT查询,返回受影响的行数
return cursor.rowcount
# 使用示例
results = execute_query(
"SELECT name, age FROM myapp_person WHERE age > %s",
[25]
)
Django原生SQL查询
raw方法
直接数据库连接
返回模型实例
支持模型方法
自动字段映射
connection.cursor
返回原始数据
手动结果处理
执行查询
SELECT查询
写操作
fetchall
fetchone
fetchmany
INSERT
UPDATE
DELETE
元组格式
字典格式转换

注意事项

  1. SQL注入防护:始终使用参数化查询,不要直接拼接字符串

    # ✅ 安全:使用参数化查询
    cursor.execute("SELECT * FROM users WHERE username = %s", [username])
    # ❌ 危险:字符串拼接(SQL注入风险)
    cursor.execute(f"SELECT * FROM users WHERE username = '{username}'")
    # ❌ 危险:直接传递用户输入
    cursor.execute("SELECT * FROM users WHERE username = %s" % username)
  2. 表名引用:在SQL中使用实际的数据库表名,而不是模型名

  3. 性能考虑:原生SQL通常更快,但失去了Django ORM的一些便利功能;使用直接连接:需要最高性能、复杂查询或跨表查询

  4. 数据库兼容性:如果你使用多个数据库后端,要注意SQL语法的差异

这些方法让你在需要优化性能或执行复杂查询时,能够灵活地使用原生SQL,同时保持代码的安全性和可维护性。

http://www.jsqmd.com/news/44995/

相关文章:

  • [nanoGPT] ChatGPT 的 LLM 的全栈实现 | 快速上手 - 实践
  • QQ浏览器的制作
  • 端点漏洞防护技术解析
  • 爱与时间反应鲜红色慢慢退却 一次次重复直到忘记了誓言 放弃这无果努力不再浪费时间 让心忘记所有感觉 直到永远
  • [Python刷题记录]-搜索插入位置-二分查找-简单
  • 告别低效备考!2025雅思封闭班培训机构深度测评
  • mariadb galera集群在Openstack中的应用 - T
  • webtui+chawan 搭建兼容TUI与HTML的UI
  • 实用指南:ArrayList与LinkedList对比:从源码角度分析性能差异ki
  • WPF Prism.Wpf implements mvvm,Prism.DryIOC implements IOC,IEventAggregator pub and sub message
  • linux ftp慢
  • 面试官问你这些,其实是在问你JavaScript执行原理!
  • Linux学习记录(七):WSL
  • 11/18
  • 2025年11月水泵,多级水泵,消防水泵公司推荐:扬程适配性与能效等级测评
  • 软件工程学习日志2025.11.19
  • linux ftp地址
  • 2025年11月消防水泵,多级水泵,自吸水泵厂家推荐:高温工况适用机型优选
  • linux ftp同步
  • 2025年11月水泵,管道水泵,多级水泵厂家推荐:大流量机型实测与采购攻略
  • 11/19
  • Longest Palindromic Substring最长回文子串-Manacher算法
  • [20251113]建立完善fffext.sh脚本.txt
  • ubuntu25 win11 双系统 和一些常用配置
  • 解码线程调度与信号响应
  • LEANN:一个极简的本地向量数据库
  • extern C的深入理解
  • 详细介绍:技术人互助:城市级充电系统(Java 微服务)的落地细节,含 demo 和设备适配经验
  • 浅记树分块
  • XPath表达式解析与应用