在Django REST Framework中通过ID获取IssueReport模型数据报错求助
Django REST Framework 通过ID获取IssueReport数据的问题排查与解决
问题描述
我想在Django REST Framework中通过ID获取IssueReport模型的数据,于是用POST方法手动传递ID来获取对应数据,但遇到两个问题:
- 发送GET请求到接口时提示Method Not Allowed
- 发送POST请求时触发
IssueReport.DoesNotExist异常
报错信息
Method Not Allowed: /app/auth/getissuereport/ [10/Aug/2022 23:26:21] "GET /app/auth/getissuereport/ HTTP/1.1" 405 7036 Internal Server Error: /app/auth/getissuereport/ Traceback (most recent call last): File "D:\MMRDA\.venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File "D:\MMRDA\.venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "D:\MMRDA\.venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view return view_func(*args, **kwargs) File "D:\MMRDA\.venv\lib\site-packages\django\views\generic\base.py", line 84, in view return self.dispatch(request, *args, **kwargs) File "D:\MMRDA\.venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch response = self.handle_exception(exc) File "D:\MMRDA\.venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception self.raise_uncaught_exception(exc) File "D:\MMRDA\.venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception raise exc File "D:\MMRDA\.venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch response = handler(request, *args, **kwargs) File "D:\MMRDA\mmrda\apis\views.py", line 195, in post report=IssueReport.objects.get(pk=id) File "D:\MMRDA\.venv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "D:\MMRDA\.venv\lib\site-packages\django\db\models\query.py", line 496, in get raise self.model.DoesNotExist( DataSet.models.IssueReport.DoesNotExist: IssueReport matching query does not exist.
现有代码
views.py
class GetIssueReportById(generics.GenericAPIView): serializer_class=GetIssueReportSerializer def post(self,request,*args,**kwargs): serializer=self.get_serializer(data=request.data) if serializer.is_valid(raise_exception=True): id=serializer.data.get('id') report=IssueReport.objects.get(pk=id) data=IssueReportSerializer(report,context=self.get_serializer_context()).data return Response({ 'message':"Data Fetched successfully", 'status':"success", 'data':data, },status=status.HTTP_200_OK) else: return Response({ 'message':"Data not fetched", 'status':status.HTTP_400_BAD_REQUEST })
serializers.py
class IssueReportSerializer(serializers.ModelSerializer): class Meta: model=IssueReport fields='__all__' class GetIssueReportSerializer(serializers.ModelSerializer): class Meta: model=IssueReport fields=('id',)
问题解决与优化
1. 解决Method Not Allowed(GET请求不被允许)
你的视图只实现了post方法,因此默认不处理GET请求。有两种处理方案:
方案一:添加GET方法支持
如果需要通过GET请求传ID(比如查询参数?id=1),可以在视图中添加get方法:
def get(self, request, *args, **kwargs): report_id = request.query_params.get('id') if not report_id: return Response({ 'message': "缺少id参数", 'status': "error" }, status=status.HTTP_400_BAD_REQUEST) # 用get_object_or_404替代get,避免异常 report = get_object_or_404(IssueReport, pk=report_id) data = IssueReportSerializer(report, context=self.get_serializer_context()).data return Response({ 'message': "数据获取成功", 'status': "success", 'data': data, }, status=status.HTTP_200_OK)
方案二:遵循RESTful规范(推荐)
获取单条资源的标准做法是用GET请求+URL路径参数,DRF提供了RetrieveAPIView可以直接实现这个逻辑,无需手动编写查询和序列化代码:
from django.shortcuts import get_object_or_404 from rest_framework import generics from .models import IssueReport from .serializers import IssueReportSerializer class GetIssueReportById(generics.RetrieveAPIView): queryset = IssueReport.objects.all() serializer_class = IssueReportSerializer # lookup_field默认是'id',可以省略 # lookup_field = 'id'
使用时直接请求/app/auth/getissuereport/1/(1为目标ID)即可自动返回对应数据,同时自动处理404(ID不存在时)和请求方法校验。
2. 解决POST请求触发DoesNotExist异常
这个异常的核心原因是传入的ID在数据库中不存在,或者参数传递有误。可以从以下几点优化:
- 校验ID存在性:用
get_object_or_404替代IssueReport.objects.get(),这样查询不到时会自动返回404响应,而不是抛出未捕获的异常 - 检查参数传递:确保POST请求的Body是正确的JSON格式,比如
{"id": 1},且ID确实存在于数据库中 - 使用validated_data:从
serializer.validated_data.get('id')获取ID,比serializer.data.get('id')更可靠,因为validated_data是经过验证后的数据
优化后的POST视图代码:
from django.shortcuts import get_object_or_404 class GetIssueReportById(generics.GenericAPIView): serializer_class = GetIssueReportSerializer def post(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) # 从validated_data取ID report_id = serializer.validated_data.get('id') # 自动处理不存在的情况 report = get_object_or_404(IssueReport, pk=report_id) data = IssueReportSerializer(report, context=self.get_serializer_context()).data return Response({ 'message': "数据获取成功", 'status': "success", 'data': data, }, status=status.HTTP_200_OK)
内容的提问来源于stack exchange,提问作者Arman Shaikh
相关产品推荐
相关产品推荐

