You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django测试中创建的Task查询失败,实际服务器正常问题求助

Django测试中Task查询失败问题排查

错误详情

错误:test_task_check_success (tasks.tests.TaskCheckTestCase.test_task_check_success)

回溯(最近的调用最后):
文件 "C:\Users\gns03\OneDrive\바탕 화면\사전과제\tasks\tests.py",第119行,在test_task_check_success中
response = self.client.get(self.url, params=self.data1, **header, format='json')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\rest_framework\test.py",第289行,在get中
response = super().get(path, data=data, **extra)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\rest_framework\test.py",第206行,在get中
return self.generic('GET', path, **r)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\rest_framework\test.py",第234行,在generic中
return super().generic(
^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\test\client.py",第609行,在generic中
return self.request(**r)
^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\rest_framework\test.py",第286行,在request中
return super().request(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\rest_framework\test.py",第238行,在request中
request = super().request(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\test\client.py",第891行,在request中
self.check_exception(response)
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\test\client.py",第738行,在check_exception中
raise exc_value
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\core\handlers\exception.py",第55行,在inner中
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\core\handlers\base.py",第197行,在_get_response中
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\views\decorators\csrf.py",第56行,在wrapper_view中
return view_func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\views\generic\base.py",第104行,在view中
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\rest_framework\views.py",第509行,在dispatch中
response = self.handle_exception(exc)
^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\rest_framework\views.py",第469行,在handle_exception中
self.raise_uncaught_exception(exc)
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\rest_framework\views.py",第480行,在raise_uncaught_exception中
raise exc
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\rest_framework\views.py",第506行,在dispatch中
response = handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\OneDrive\바탕 화면\사전과제\tasks\views.py",第69行,在get中
task_instance = Task.objects.get(id=request.data.get('task'))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\manager.py",第87行,在manager_method中
return getattr(self.get_queryset(), name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 "C:\Users\gns03\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\db\models\query.py",第637行,在get中
raise self.model.DoesNotExist(
tasks.models.Task.DoesNotExist: 匹配查询的Task不存在。

相关代码

views.py

class TaskCheckView(APIView):

    def get(self, request):
        

        try:
            task_instance = Task.objects.get(id=request.data.get('task'))
        except Task.DoesNotExist:
            return Response({
                'error_code': status.HTTP_404_NOT_FOUND,
                'error': '해당 업무를 찾을 수 없습니다.'}, 
                status=status.HTTP_404_NOT_FOUND)
        
 
        subtasks_related_to_task = SubTask.objects.filter(task=task_instance)

        subtasks_data = SubTaskSerializer(subtasks_related_to_task, many=True).data
        
        serializer = TaskCheckSerializer(data={
            'task_id': task_instance.id,
            'task_team': ','.join([str(team.id) for team in task_instance.team.all()]),
            'title': task_instance.title,
            'content': task_instance.content,
            'is_complete': task_instance.is_complete,
            'completed_data': task_instance.completed_data,
            'created_at': task_instance.created_at,
            'modified_at': task_instance.modified_at,
            'subtasks': subtasks_data
        })


        if serializer.is_valid():
            return Response({'data': serializer.data, 
                            'status': status.HTTP_200_OK}, 
                            status=status.HTTP_200_OK)
        
        return Response({'error_code': status.HTTP_400_BAD_REQUEST}, 
                        status=status.HTTP_400_BAD_REQUEST)

serializers.py

class TaskCheckSerializer(serializers.Serializer):
    task_id = serializers.IntegerField()
    task_team = serializers.CharField()
    title = serializers.CharField()
    content = serializers.CharField()
    is_complete = serializers.BooleanField()
    completed_data = serializers.DateTimeField(allow_null=True)
    created_at = serializers.DateField()
    modified_at = serializers.DateField()
    subtasks = SubTaskSerializer(many=True)

tests.py

class TaskCheckTestCase(APITestCase):
    def setUp(self):
        self.url = '/task/detail/'
        self.user = User.objects.create(email='test1@naver.com', name='팀원1')
        self.user.set_password("qwer1234")
        self.user.save()
        self.token, created = Token.objects.get_or_create(user=self.user)

        self.team1 = Team.objects.create(team='team1')

        self.task = Task.objects.create(title='테스트 제목', content='테스트', create_user=self.user)
        self.task.team.set([self.team1.id])  
        self.subtask = SubTask.objects.create(task=self.task, team=self.team1)
        

        self.data1={
            'task': str(self.task.id)
        }

        self.data2={
            'task': '999'
        }

    def test_task_check_success(self):
        header = {'HTTP_AUTHORIZATION': f'Token {self.token}'}
        response = self.client.get(self.url, data=self.data1, **header, format='json') 
        self.assertEqual(response.status_code, status.HTTP_200_OK)

问题描述

我在服务器中查询实际的Task ID没有问题,但运行测试代码时,查询在setUp中创建的self.task却出现错误。问题出在哪里?

我没有得到404错误,出现错误的原因是获取实例的try部分未捕获异常,直接抛出了错误信息。

问题原因与修复方案

1. GET请求参数获取方式错误

REST Framework中,request.data仅用于处理POST/PUT/PATCH等包含请求体的请求,GET请求的参数需要从request.query_params中获取。你当前在TaskCheckView.get方法中用request.data.get('task'),会导致始终获取不到GET请求传递的参数,最终查询id=None的Task,抛出DoesNotExist异常。

修复views.py:

def get(self, request):
    try:
        # 从查询参数获取task id,并转换为整数类型
        task_id = request.query_params.get('task')
        if not task_id:
            return Response({
                'error_code': status.HTTP_400_BAD_REQUEST,
                'error': 'task参数不能为空'}, 
                status=status.HTTP_400_BAD_REQUEST)
        task_instance = Task.objects.get(id=int(task_id))
    except Task.DoesNotExist:
        return Response({
            'error_code': status.HTTP_404_NOT_FOUND,
            'error': '해당 업무를 찾을 수 없습니다.'}, 
            status=status.HTTP_404_NOT_FOUND)
    except ValueError:
        return Response({
            'error_code': status.HTTP_400_BAD_REQUEST,
            'error': 'task参数必须是有效的整数'}, 
            status=status.HTTP_400_BAD_REQUEST)
    # 后续代码保持不变

2. 测试代码中参数传递优化

虽然Django测试客户端的get方法中data参数会自动转为查询参数,但更规范的写法是使用params参数明确传递查询参数,同时task直接用整数类型更严谨:

修复tests.py的test_task_check_success方法:

def test_task_check_success(self):
    header = {'HTTP_AUTHORIZATION': f'Token {self.token}'}
    # 使用params传递GET查询参数,task用整数类型
    response = self.client.get(self.url, params={'task': self.task.id}, **header) 
    self.assertEqual(response.status_code, status.HTTP_200_OK)

3. 异常捕获不完整问题

之前的代码只捕获了Task.DoesNotExist异常,但当task参数为空或不是整数时,会抛出ValueError,这个异常没有被捕获,导致直接抛出未处理的异常。上面的修复中已经添加了ValueError的捕获处理,确保所有可能的异常都被正确处理并返回对应的响应。

内容的提问来源于stack exchange,提问作者성낙훈

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 05:04:53