Django执行原生SQL的三种方式与字典封装实战

陆景行
陆景行
发布时间:2026-10-15| 4人浏览过
原创

本文详解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的教程介绍完毕。更多相关内容请查阅本站历史文章或继续浏览后续内容,感谢支持。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。