Django REST Framework:如何用kwargs替代request解析请求数据
在Django REST Framework中直接将请求参数映射为视图函数参数
要解决函数内部手动解析request.data导致数据流难追踪的问题,可通过自定义装饰器自动完成请求参数到视图函数命名参数的映射,以下是两种可行方案:
方案一:基础参数解析装饰器
该装饰器通过识别函数参数定义,自动从request.data提取对应值并做类型转换,同时保留参数默认值:
import inspect from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.exceptions import ValidationError def inject_request_params(func): def wrapper(request, *args, **kwargs): sig = inspect.signature(func) parsed_params = {} for param_name, param in sig.parameters.items(): # 从请求体获取参数,无值则使用默认值 raw_value = request.data.get(param_name, param.default) # 根据参数类型注解尝试转换类型 if param.annotation != inspect.Parameter.empty: try: parsed_params[param_name] = param.annotation(raw_value) except (ValueError, TypeError): raise ValidationError(f"参数 {param_name} 类型错误,需为 {param.annotation.__name__} 类型") else: parsed_params[param_name] = raw_value return func(**parsed_params) return wrapper
修改后的视图函数可直接使用命名参数:
@api_view(["POST"]) @permission_classes([IsAuthenticated]) @inject_request_params def greet(user: str = 'test', friend: str = 'bart', num_friends: int = 16): # 无需手动解析request.data,直接使用参数 return None
方案二:结合DRF序列化器(推荐生产环境)
若需要更严谨的参数校验、错误提示和数据清洗,可结合DRF序列化器实现:
- 定义参数验证序列化器:
from rest_framework import serializers class GreetRequestSerializer(serializers.Serializer): user = serializers.CharField(default='test') friend = serializers.CharField(default='bart') num_friends = serializers.IntegerField(default=16)
- 调整装饰器,用序列化器做参数解析:
def inject_request_params(func): def wrapper(request, *args, **kwargs): serializer = GreetRequestSerializer(data=request.data) # 验证失败自动抛出DRF标准400错误 serializer.is_valid(raise_exception=True) # 将验证后的参数传入视图函数 return func(**serializer.validated_data) return wrapper
- 视图函数保持目标代码的简洁形式:
@api_view(["POST"]) @permission_classes([IsAuthenticated]) @inject_request_params def greet(user: str = 'test', friend: str = 'bart', num_friends: int = 16): return None
此方案利用DRF成熟的序列化机制,能提供专业的参数校验和错误反馈,更适合生产环境使用。
内容的提问来源于stack exchange,提问作者Sam Shleifer
相关产品推荐
相关产品推荐

