Django REST Framework 统一请求参数解析指南
本文详解 Django REST Framework 中如何统一解析不同 HTTP 方法的请求参数。通过判断 request.query_params 和 request.data,将 QueryDict 转换为标准字典,实现 GET、POST、PUT 等请求参数的统一处理,简化后端逻辑开发。
前言与背景
前言
在之前的 Django REST Framework 自定义 Swagger 文章里,我们已经成功编写并调通了接口文档。虽然接口文档支持直接填写参数进行请求,但接下来的核心问题是如何在服务器端正确接收这些参数。由于 HTTP 请求方式多样且参数序列化格式各异,接收参数的具体策略也需随之调整。
前提条件与接口基础
前提条件
服务端接口开发基于 Django REST Framework 框架进行。
class ReturnJson(APIView):
coreapi_fields=(
DocParam("token"),
)
def get(self, request, *args, **kwargs):
return JsonResponse("Hello world!!!!!!!!++++++中文测试")
这是一个基础示例接口,其中 ReturnJson 类继承自 APIView。
该 APIView 类来源于 from rest_framework.views import APIView。
以下所有关于 def get、def post 等方法的讨论,前提条件均为接口类必须继承自 APIView。
当然,开发者也可以选择继承其他类,例如 viewsets 或 generics 模块中的类。
from rest_framework import viewsets, generics
class ReturnJson(generics.ListCreateAPIView)
class ReturnJson(viewsets.ModelViewSet)
这些不同类的用法各有侧重,具体细节请参考官方文档。
- http://www.django-rest-framework.org/api-guide/viewsets/
- http://www.django-rest-framework.org/api-guide/generic-views/
- http://www.django-rest-framework.org/api-guide/views/
了解 Django REST Framework 如何编写一个标准接口是基础。
class ReturnJson(APIView):
coreapi_fields=(
DocParam("token"),
)
def get(self, request, *args, **kwargs):
return JsonResponse("Hello world!!!!!!!!++++++中文测试")
def post(self, request, *args, **kwargs):
return JsonResponse(data={})
def put(self, request, *args, **kwargs):
return JsonResponse(data={})
Request 对象与参数解析原理
对于 APIView 的子类而言,重写 get、post、put 等方法,本质上就是解析对应路径下的 GET、POST、PUT 请求。
请求对象即为 request 对象,HTTP Header 和 Body 的内容均包含在该对象中。request 对象的类定义来自 from rest_framework.request import Request。
我们需要判断对象是否为某个类的实例。
from rest_framework.request import Request
if isinstance(request, Request)
接下来将分别分析不同情况下参数的位置和类型,最终编写一个方法,将任何类型的请求参数统一转换为 dict 格式,以便后续逻辑处理。
不同 HTTP 方法的参数处理策略
GET 请求处理
在 GET 请求中,参数通常会以 http://xxx.com/api/getjson?param1=asdf¶m2=123 的形式拼接在 URL 后面。
在 request 对象内部,
- 可以通过 request.query_params 获取 ?param1=32¶m2=23 形式的参数。
- 需要注意的是,request.query_params 返回的数据类型为 QueryDict。
- 若需将 QueryDict 转换为普通 Python 字典,只需调用 query_params.dict() 即可。
POST 请求处理
POST 请求的参数通常位于请求体中。虽然理论上 URL 可以写成 GET 形式,导致参数一部分在 URL 中、一部分在 HTTP Body 中,但非常不建议这样做。
后续代码编写不考虑上述混合情况,仅处理所有参数均位于 HTTP Body 中的标准 POST 请求。
| 提交类型 | 参数位置 | 参数类型 |
|---|---|---|
| form-data提交, | 参数在data中, | 类型为QueryDict |
| application/json提交 | 参数在data中 | 类型为dict |
| (swagger)使用接口文档提交, 由于使用curl提交, 虽然是post 但是参数依然被类似get的形式拼接到了url之后, | 此时 参数在query_params 中 | 类型为 QueryDict |
| x-www-form-urlencoded | 参数在data中 | 类型为 QueryDict |
PUT 请求处理
| 提交类型 | 参数位置 | 参数类型 |
|---|---|---|
| form-data | request.data | QueryDict |
| application/json | request.data | dict |
| x-www-form-urlencoded | request.data | QueryDict |
| (swagger) | request.data | dict |
PATCH 请求处理
| 提交类型 | 参数位置 | 参数类型 |
|---|---|---|
| form-data | request.data | QueryDict |
| application/json | request.data | dict |
| x-www-form-urlencoded | request.data | QueryDict |
| (swagger) | request.data | dict |
DELETE 请求处理
| 提交类型 | 参数位置 | 参数类型 |
|---|---|---|
| form-data | request.data | QueryDict |
| application/json | request.data | dict |
| x-www-form-urlencoded | request.data | QueryDict |
| (swagger) | request.query_params | QueryDict |
| iOS端提交和get情况一样 | request.query_params | QueryDict |
统一参数处理方法实现
编写参数统一处理方法
总结来说,当 URL 包含 ?param=1¶m=2 这样的参数时(如 GET 或 DELETE 提交),应忽略 Body 中的参数。如果 query_params 有内容,则优先返回 query_params,并将其转为 dict;若 query_params 为空,再判断 request.data 中是否有内容及其类型。
from django.http import QueryDict
from rest_framework.request import Request
def get_parameter_dic(request, *args, **kwargs):
if isinstance(request, Request) == False:
return {}
query_params = request.query_params
if isinstance(query_params, QueryDict):
query_params = query_params.dict()
result_data = request.data
if isinstance(result_data, QueryDict):
result_data = result_data.dict()
if query_params != {}:
return query_params
else:
return result_data
代码应用与总结
使用方法
class ReturnJson(APIView):
coreapi_fields=(
DocParam("token"),
)
def get(self, request, *args, **kwargs):
params=get_parameter_dic(request)
return JsonResponse(data=params)
def post(self, request, *args, **kwargs):
params=get_parameter_dic(request)
return JsonResponse(data=params)
def put(self, request, *args, **kwargs):
params=get_parameter_dic(request)
return JsonResponse(data=params)
最终实现效果如下。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













