Django使用ModelViewSet时如何获取PATCH请求URL中的id参数?
你在initialize_request中无法正确获取id的核心原因是:DRF的路由参数解析流程晚于initialize_request的执行,在该方法执行时self.kwargs还没有被赋值,你调用MyModel.objects.get()时没有传入过滤条件,才会返回多个对象报错。
可选解决方案
方法1:在initialize_request中手动解析请求路径
如果必须在initialize_request阶段获取id,可以通过正则匹配请求路径提取目标值:
import re from rest_framework.viewsets import ModelViewSet from .models import MyModel from .serializers import MyModelSerializer class MyModelViewSet(ModelViewSet): queryset = MyModel.objects.all() serializer_class = MyModelSerializer def initialize_request(self, request, *args, **kwargs): # 先执行父类逻辑拿到标准request对象 request = super().initialize_request(request, *args, **kwargs) # 正则匹配路径中的id值,规则可根据你的实际路由调整 path = request.path_info id_match = re.search(r'/api/details/(\d+)/', path) if id_match: target_id = int(id_match.group(1)) # 此时就可以用过滤条件查询单条对象 target_instance = MyModel.objects.get(id=target_id) # 执行你需要的业务逻辑 return request
方法2:更换到后续生命周期钩子获取(更推荐)
如果没有强需求必须在initialize_request中处理,更建议在路由参数解析完成后的钩子中操作,不需要手动解析路径:
class MyModelViewSet(ModelViewSet): queryset = MyModel.objects.all() serializer_class = MyModelSerializer def get_object(self): # 路由解析完成后可以直接从kwargs中拿主键,参数名和路由定义保持一致即可 target_id = self.kwargs.get('pk') target_instance = MyModel.objects.get(id=target_id) # 执行你需要的业务逻辑 return super().get_object()
注意事项
- 如果自定义路由的主键参数名不是
pk,把self.kwargs.get('pk')的key替换为你实际定义的参数名即可 - 手动解析路径时正则规则需要和你的路由配置完全匹配,避免匹配到错误数值
内容的提问来源于stack exchange,提问作者Anirban Nag 'tintinmj'
相关产品推荐
相关产品推荐

