如何通过单次Axios请求实现基于my_id的Django REST Framework数据更新?
问题描述
我使用Django REST Framework进行后端开发,前端通过Axios与后端做数据交互。目前的实现逻辑是先通过my_id查询获取用户的id,再用该id发送PATCH请求更新数据,代码如下:
axios.get(`http://localhost:8010/api/myusers/?my_id=${my_id}`).then((res)=>{ var id = res['data']['results'][0]['id']; axios.patch(`http://localhost:8010/api/myusers/${id}/`, { phone: 'nice phone', }).then((res)=>{ console.log("patch finish"); }) })
这种方式需要两次请求,流程繁琐。我尝试直接通过查询参数my_id发送PATCH请求,却收到405 Method not allowed错误:
axios.patch(`http://localhost:8010/api/myusers/?my_id=${my_id}`, { phone: 'nice phone2', }).then((res)=>{ console.log("patch finish"); })
后端使用DRF和django-filter的配置如下:
class MyUserViewSet(viewsets.ModelViewSet): queryset = sm.MyUser.objects.all() serializer_class = sl.MyUserSerializer filter_backends = [DjangoFilterBackend] search_fields = ['my_id'] filterset_fields = ['my_id'] class MyUserSerializer(serializers.ModelSerializer): class Meta: model = sm.MyUser fields = ('my_id','phone','id','created_at')
想实现单次请求完成数据更新,该怎么做?
解决方案
方法一:自定义ViewSet动作
在MyUserViewSet中新增一个专门处理my_id更新的自定义PATCH动作:
from rest_framework.decorators import action from rest_framework.response import Response from rest_framework import status class MyUserViewSet(viewsets.ModelViewSet): queryset = sm.MyUser.objects.all() serializer_class = sl.MyUserSerializer filter_backends = [DjangoFilterBackend] search_fields = ['my_id'] filterset_fields = ['my_id'] @action(detail=False, methods=['patch'], url_path='update-by-my-id') def update_by_my_id(self, request): my_id = request.query_params.get('my_id') if not my_id: return Response({'error': 'my_id参数必填'}, status=status.HTTP_400_BAD_REQUEST) try: user = self.queryset.get(my_id=my_id) except sm.MyUser.DoesNotExist: return Response({'error': '用户不存在'}, status=status.HTTP_404_NOT_FOUND) serializer = self.get_serializer(user, data=request.data, partial=True) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data)
前端请求修改为:
axios.patch(`http://localhost:8010/api/myusers/update-by-my-id/?my_id=${my_id}`, { phone: 'nice phone2', }).then((res)=>{ console.log("patch finish"); })
方法二:将my_id设为详情路由参数
如果my_id在数据库中是唯一值,可以直接修改ViewSet的路由匹配规则,用my_id替代默认的id作为详情标识:
class MyUserViewSet(viewsets.ModelViewSet): queryset = sm.MyUser.objects.all() serializer_class = sl.MyUserSerializer filter_backends = [DjangoFilterBackend] search_fields = ['my_id'] filterset_fields = ['my_id'] lookup_field = 'my_id' # 替换默认的id为my_id
前端直接用my_id作为路径参数发送请求:
axios.patch(`http://localhost:8010/api/myusers/${my_id}/`, { phone: 'nice phone2', }).then((res)=>{ console.log("patch finish"); })
注意:此方法要求my_id必须唯一,否则会因匹配到多个用户而报错;若my_id不唯一,优先选用方法一。
内容的提问来源于stack exchange,提问作者whitebear
相关产品推荐
相关产品推荐

