Django单元测试报错:'TemplateResponse'对象无'data'属性
问题分析与解决
错误根源
- 请求路径无效:
self.client.get('')没有指向PostList对应的API路由,导致Django返回了模板响应(而非API的JSON响应),因此response是TemplateResponse对象,不存在data属性。 - 测试逻辑颠倒:
test_get_queryset_superuser中登录的是普通用户,test_get_queryset_author中登录的是超级用户,完全和测试目标相反。 - 未指定响应格式:即使路径正确,若未明确要求JSON响应,Django可能返回API文档的HTML页面,同样会得到
TemplateResponse。
修复方案
1. 配置并使用正确的API路由
先确认你的urls.py中PostList的路由配置,示例如下:
# urls.py from django.urls import path from .views import PostList urlpatterns = [ path('api/posts/', PostList.as_view(), name='post-list'), ]
测试时用reverse生成正确的URL,避免硬编码路径。
2. 修正测试中的用户登录逻辑
将测试方法里的登录用户调换,确保超级用户测试用超级账号登录,普通作者测试用普通账号登录。
3. 指定请求接受JSON格式
在get请求中添加HTTP_ACCEPT='application/json',强制返回API的JSON响应。
修复后的完整测试代码
from django.urls import reverse from rest_framework import status class PostListTestCase(APITestCase): def setUp(self): self.author = NewUser.objects.create_user( email='testuser@testuser.com', user_name='test11', first_name="test11", password='Family123!') self.superuser = NewUser.objects.create_superuser( email='admin@admin.com', user_name='admin', first_name="admin", password='Family123!') self.post1 = JobPost.objects.create( title="Job Post 1", place="Test Place 1", description="Test description 1", job_date="2023-05-20", status="undone", slug="job-post-1", reward=1, author=self.author,) self.post2 = JobPost.objects.create( title="Job Post 2", place="Test Place 2", description="Test description 2", job_date="2023-05-22", status="done", slug="job-post-2", reward=1, author=self.superuser,) # 提前获取API路由的URL self.api_url = reverse('post-list') def test_get_queryset_superuser(self): # 登录超级用户 self.client.login(email='admin@admin.com', password='Family123!') # 请求时指定接受JSON格式 response = self.client.get(self.api_url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, status.HTTP_200_OK) # 超级用户应获取所有帖子 all_posts = JobPost.objects.all() serializer = JobPostSerializer(all_posts, many=True) self.assertEqual(response.data, serializer.data) def test_get_queryset_author(self): # 登录普通作者用户 self.client.login(email='testuser@testuser.com', password='Family123!') response = self.client.get(self.api_url, HTTP_ACCEPT='application/json') self.assertEqual(response.status_code, status.HTTP_200_OK) # 普通用户只能获取自己发布的帖子 user_posts = JobPost.objects.filter(author=self.author) serializer = JobPostSerializer(user_posts, many=True) self.assertEqual(response.data, serializer.data)
额外检查项
- 确认
PostList视图在urls.py中的路由配置正确,未被其他模板视图覆盖。 - 验证
JobPostSerializer的序列化逻辑,确保能正确处理JobPost模型的所有字段。
内容的提问来源于stack exchange,提问作者User G Amsterdam
相关产品推荐
相关产品推荐

