如何在Django REST Framework APIView中配置URL路径ID参数
解决方案
1. 修改urls.py
调整路由规则,使其同时兼容带路径ID和不带路径ID的请求,同时不影响原有?id=xxx的用法:
# 若使用Django 3.x及以上版本,导入re_path from django.urls import re_path from .views import playerList urlpatterns = [ # 同时匹配 /api/players/ 和 /api/players/数字/ 两种格式 re_path(r'^players/(?:(?P<id>\d+)/?)?$', playerList.as_view()), ]
正则说明:<id>捕获路径中的数字作为参数传入视图,规则同时兼容路径末尾带/和不带/的请求。
2. 修改views.py
调整各个请求方法的ID获取逻辑,优先从路径参数中取ID,路径没有ID再查询URL参数:
修改get方法
def get(self, request, *args, **kwargs): # 优先取路径参数中的id id = kwargs.get('id') # 路径没有id再查查询参数 if not id: id = request.query_params.get("id") if id: try: player_object = player.objects.get(id=id) serializer = playerSerializer(player_object) return Response(serializer.data) except player.DoesNotExist: return Response({"error": "球员不存在"}, status=status.HTTP_404_NOT_FOUND) # 没有id返回全部球员列表 players = self.get_queryset() serializer = playerSerializer(players, many=True) return Response(serializer.data)
修改put方法
def put(self, request, *args, **kwargs): id = kwargs.get('id') or request.query_params.get("id") if not id: return Response({"error": "请传入球员id"}, status=status.HTTP_400_BAD_REQUEST) try: player_object = player.objects.get(id=id) except player.DoesNotExist: return Response({"error": "球员不存在"}, status=status.HTTP_404_NOT_FOUND) data = request.data player_object.first_name = data["first_name"] player_object.last_name = data["last_name"] player_object.team = data["team"] player_object.position = data["position"] player_object.number = data["number"] player_object.save() serializer = playerSerializer(player_object) return Response(serializer.data)
修改patch方法
def patch(self, request, *args, **kwargs): id = kwargs.get('id') or request.query_params.get("id") if not id: return Response({"error": "请传入球员id"}, status=status.HTTP_400_BAD_REQUEST) try: player_object = player.objects.get(id=id) except player.DoesNotExist: return Response({"error": "球员不存在"}, status=status.HTTP_404_NOT_FOUND) data = request.data player_object.first_name = data.get('first_name', player_object.first_name) player_object.last_name = data.get('last_name', player_object.last_name) player_object.team = data.get('team', player_object.team) player_object.position = data.get('position', player_object.position) player_object.number = data.get('number', player_object.number) player_object.save() serializer = playerSerializer(player_object) return Response(serializer.data)
3. 可选优化建议
- 遵循Python PEP8命名规范,模型类名首字母大写,
player改为Player,视图类playerList改为PlayerList,提升代码可读性 - 增改操作可以直接使用序列化器的
save()方法,无需手动逐个字段赋值,同时自动完成参数校验,减少异常处理成本 - 可以使用DRF的
ModelViewSet直接生成完整的增删改查接口,无需手动编写每个请求方法的逻辑,大幅简化代码
内容的提问来源于stack exchange,提问作者Austin Hallett
相关产品推荐
相关产品推荐

