Django Rest Framework是否支持复杂原生SQL查询与接口返回?
DRF 原生SQL查询问题解答
核心结论
- DRF 完全支持执行涉及多表关联的复杂原生SQL,不需要额外搭配专门的SQL执行组件,直接用Django内置的数据库连接模块即可实现
- 原生SQL的查询结果完全可以通过GET请求正常返回给Angular前端,不存在框架层面的限制
- 不需要强制绑定Django ORM模型、DRF 模型序列化器才能返回数据,这是很多DRF初学者的常见误区
具体实现方式
直接通过Django内置的connection对象创建游标执行SQL即可,配合DRF最基础的APIView就能快速写好接口,示例代码如下:
from django.db import connection from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class OrderDataQueryView(APIView): def get(self, request): # 读取前端GET请求传的筛选参数 query_user_id = request.query_params.get("user_id") query_start_time = request.query_params.get("start_time") # 替换成你拿到的现成复杂SQL,参数位置用%s做占位 # 示例是三表关联的查询,你可以直接替换自己的多表关联SQL raw_sql = """ SELECT u.id AS user_id, u.username, o.order_sn, o.pay_amount, og.goods_title, og.buy_num FROM user_info u LEFT JOIN user_order o ON u.id = o.user_id LEFT JOIN order_goods og ON o.id = og.order_id WHERE u.id = %s AND o.create_time >= %s """ with connection.cursor() as cursor: # 参数化执行SQL,禁止直接拼接前端参数到SQL字符串,避免SQL注入 cursor.execute(raw_sql, [query_user_id, query_start_time]) # 拉取所有查询结果 result_list = cursor.fetchall() # 读取查询返回的字段名,和结果行组装成字典列表 field_names = [item[0] for item in cursor.description] formatted_data = [dict(zip(field_names, row)) for row in result_list] # 如果有需要可以在这里加数据脱敏、字段格式转换的逻辑 return Response(formatted_data, status=status.HTTP_200_OK)
注意事项
- 参数传递必须走
cursor.execute的参数位,绝对不要用f-string、字符串拼接的方式把前端传入的参数直接拼到SQL语句里,Django会自动对传入参数做转义,从根源避免SQL注入风险 - 如果查询返回的数据量较大,可以直接搭配DRF自带的分页类做分页,把查询得到的列表传给分页类的
paginate_queryset方法即可,不需要额外开发分页逻辑 - 因为是Angular+Django的前后端分离架构,只需要常规配置
django-cors-headers允许前端域名跨域访问即可,这个配置和是否使用原生SQL没有关系,是所有前后端分离Django项目的常规操作 - 如果你后续需要做接口权限控制、访问频率限制,直接在视图类上加DRF自带的权限类、限流类即可,和普通ORM写的接口没有任何区别
- 不需要硬把现成的原生SQL改写成Django ORM的关联查询语法,直接复用已经验证过的SQL脚本反而能减少逻辑出错的概率,开发效率更高
内容的提问来源于stack exchange,提问作者LA.
相关产品推荐
相关产品推荐

