Django执行原生SQL的三种方式与字典封装实战
本文详解Django中执行原生SQL的三种方式:extra、raw及connection。重点讲解如何通过django.db.connection获取游标并封装query_all_dict与query_one_dict函数,实现将查询结果直接转换为字典列表,避免与Model绑定,提升开发灵活性。
前言
大家好,本期内容将介绍如何在Django框架中执行原生SQL语句。
作为Python Web开发的主流框架,Django提供了丰富的功能组件,包括插件、Forms表单、Model模型以及Admin后台管理等,整体架构成熟且强大。
本文将聚焦于Django中执行原生SQL的具体实现方法。
背景
在常规Django开发中,使用内置的Model查询功能通常能满足80%的业务需求。
然而,剩余的20%复杂查询场景往往需要更灵活的处理方式,不能忽略。
在Django中执行原生SQL主要包含以下三种方式:
- extra
- raw
- django connection
通常情况下,上述三种方式涵盖了Django执行原生SQL的主要手段。
表结构设计
文件路径:django_project/app01/models
class Book(models.Model):
title = models.CharField(verbose_name="书名", max_length=32)
describe = models.TextField(verbose_name="描述")
author = models.CharField(verbose_name="作者", max_length=32)
publisher = models.CharField(verbose_name="出版社", max_length=32)
publisher_date = models.DateField(verbose_name="publisher")
这里定义了一个基础的图书数据表模型。
可通过Admin后台录入测试数据以验证查询效果。

extra方式
建议不推荐使用此方式,因其实际应用场景较少。
raw方式
相比extra,raw方式具有更高的实用价值。
其基本语法如下:
models.表名.objecs.raw(sql)
models.表名.objecs.raw(sql,[参数1,参数2])
注意:若SQL语句无参数,直接传入SQL字符串即可;若包含参数,需在SQL后附加参数列表,具体示例如图所示。
执行示例如下:

该方式返回的结果仍为Book模型对象列表。
真正的原生SQL实现
上述方式仍与Django Model存在绑定关系。若希望完全脱离Model,直接使用原生SQL,可采用以下方法。
需特别注意:切勿在Django中使用pymysql直接执行原生SQL,以免引发异常。正确做法是导入from django.db import connection模块来执行SQL。代码示例如下:
from django.db import connection
def book_list(request):
# 真正的原生sql,
cursor = connection.cursor()
print(type(cursor))
cursor.execute("select * from app01_book where id=%s", [1, ])
raw = cursor.fetchall()
print(raw)
执行结果如图所示:

可以看到,返回结果为列表嵌套元组的格式。为了优化使用体验,我们探讨如何将查询结果直接转换为字典格式。
执行原生SQL并返回字典格式
我们将执行原生SQL并返回字典的功能封装为两个独立函数。
用于查询多条记录的函数代码如下:
def query_all_dict(sql, params=None):
'''
查询所有结果返回字典类型数据
:param sql:
:param params:
:return:
'''
with connection.cursor() as cursor:
if params:
cursor.execute(sql, params=params)
else:
cursor.execute(sql)
col_names = [desc[0] for desc in cursor.description]
row = cursor.fetchall()
rowList = []
for list in row:
tMap = dict(zip(col_names, list))
rowList.append(tMap)
return rowList
用于查询单条记录的函数代码如下:
def query_one_dict(sql, params=None):
"""
查询一个结果返回字典类型数据
:param sql:
:param params:
:return:
"""
with connection.cursor() as cursor:
if params:
cursor.execute(sql, params=params)
else:
cursor.execute(sql)
col_names = [desc[0] for desc in cursor.description]
row = cursor.fetchone()
tMap = dict(zip(col_names, row))
return tMap
在视图中直接调用上述函数即可使用。

返回结果格式为列表嵌套字典,便于后续处理。

对于带条件的查询,处理方式与pymysql类似。

具体返回结果如下:

需要注意的是,即使查询结果明确只有一条数据,上述通用方法仍返回列表嵌套字典格式,这可能在某些场景下不够直观。
针对仅查询单条数据的场景,建议使用封装好的query_one_dict方法。


总结
Django中执行原生SQL共有三种方式:extra、raw以及from django.db import connection。
其中,extra方式实用性较低;raw方式尚可,但与Model绑定;connection方式最为灵活,但默认返回格式为列表嵌套元组。
经过优化封装,我们提供了query_all_dict和query_one_dict两个方法,分别用于查询多条和单条数据,并统一返回列表嵌套字典格式。
建议
推荐直接使用封装后的query_all_dict和query_one_dict方法。
项目源码
django_exec_sql.zip
如需获取本文完整代码,可在本公众号后台回复关键字“原生SQL”进行获取。
总结
本文以入门视角系统介绍了Django执行原生SQL的方法。
保持积极心态,今日之努力胜过昨日,未来亦复如是。
至此,关于Django执行原生SQL的教程介绍完毕。更多相关内容请查阅本站历史文章或继续浏览后续内容,感谢支持。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













