Django REST Framework函数视图GET/PUT/DELETE接口失效排查
排查city_detail视图无法运行的问题
以下是几个关键问题点,按优先级排序:
1. 权限类方法缩进错误
在permissions.py中,has_object_permission方法的缩进不正确,它当前是全局函数,而非IsOwnerOrReadOnly类的成员方法。这会导致DRF无法识别权限判断逻辑,直接触发权限验证失败。
修复后的代码:
from rest_framework import permissions class IsOwnerOrReadOnly(permissions.BasePermission): """ Custom permission to only allow owners of an object to edit it. """ # 修正缩进,使方法属于类成员 def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request, # So we'll always allow GET, HEAD or OPTIONS requests. if request.method in permissions.SAFE_METHODS: return True # Write permissions are only allowed to the owner of the city. return obj.owner == request.user
2. 装饰器顺序错误
city_detail视图的装饰器顺序颠倒,DRF要求@api_view必须放在@permission_classes前面。因为@api_view会为函数视图注入DRF核心处理逻辑,@permission_classes依赖该逻辑才能正常工作。
修复后的视图装饰器:
@api_view(['GET', 'PUT', 'DELETE']) @permission_classes([IsAuthenticated, IsOwnerOrReadOnly]) def city_detail(request, pk, format=None): # ... 原有代码 ...
3. 使用Django原生响应替代DRF Response
city_detail中使用了JsonResponse和HttpResponse,而非DRF提供的Response类,这会导致:
- DRF的内容协商(格式后缀、Accept头)失效
- 权限验证后的错误信息无法正确格式化
- 无法利用DRF的异常处理机制
修复后的响应代码:
from rest_framework.response import Response # ... 其他必要导入 ... def city_detail(request, pk, format=None): """ Retrieve, update or delete a city. """ try: city = City.objects.get(pk=pk) except City.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'GET': serializer = CitySerializer(city) return Response(serializer.data) elif request.method == 'PUT': serializer = CitySerializer(city, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE': city.delete() return Response(status=status.HTTP_204_NO_CONTENT)
4. 冗余的URL配置
app.urls.py中存在path('cities/create/', views.city_create),但city_list已支持POST方法创建城市,该路由属于冗余配置,可能导致路由冲突或逻辑混淆。若未实现city_create视图,访问该URL还会触发视图不存在的错误,建议删除该路由。
额外小问题
city_detail的文档字符串描述为"Retrieve, update or delete a code snippet.",应改为对应城市的描述(如"Retrieve, update or delete a city."),提升代码可维护性。
内容的提问来源于stack exchange,提问作者Ramzouu
相关产品推荐
相关产品推荐

