如何测试Django中带有@login_required装饰器的视图?
解决Django带@login_required视图的测试上下文断言问题
问题根源
你遇到的错误是因为测试时实际访问的是登录页面(而非目标视图),导致response.context里没有预期的name键。可能的原因包括:
- 登录操作未成功执行
- 请求方法不匹配(比如视图只处理GET,但测试用了POST)
reverse用法错误导致路由跳转异常follow=True跟进了重定向,最终响应是登录页而非目标视图
修复步骤
验证登录是否成功
client.login()会返回布尔值表示登录状态,在setUp里添加断言确保登录成功,避免因登录失败跳转到登录页:def setUp(self): self.client = Client() # 断言登录成功,否则直接抛出错误 login_success = self.client.login(username='1', password='Pass@123') self.assertTrue(login_success, "登录失败,请检查用户名和密码是否正确")修正
reverse的用法reverse需要传入视图的名称字符串(对应urls.py中path的name参数),而非直接传视图函数对象:# 假设urls.py中该视图的name是'my_view' url = reverse('my_view')使用正确的请求方法
如果你的my_view是处理GET请求(通常渲染页面的视图是GET),测试时改用get方法,而非post:response = self.client.get(url)(如果视图确实需要POST,确保请求参数正确,且视图支持POST方法)
移除不必要的
follow=True
登录成功后访问视图不会触发重定向,follow=True会导致客户端跟进可能的错误重定向,最终拿到的是登录页响应,因此直接移除该参数。
修改后的完整测试代码
from django.test import TestCase, Client from django.urls import reverse from django.contrib.auth.decorators import login_required from django.shortcuts import render from django.contrib.auth.models import User @login_required def my_view(request): # 补充name变量的定义(原代码中缺失) name = "测试名称" context={'name':name} # 注意:home.html需要加引号 return render(request, 'home.html', context) class TestEmployer(TestCase): def setUp(self): self.client = Client() # 创建测试用户,避免依赖数据库中已存在的账号 self.user = User.objects.create_user(username='1', password='Pass@123') login_success = self.client.login(username='1', password='Pass@123') self.assertTrue(login_success, "登录失败,请检查账号信息") def test_list_employer(self): # 替换为urls.py中视图对应的name值 url = reverse('my_view') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertIn('name', response.context) # 还可以额外断言name的值是否正确 self.assertEqual(response.context['name'], "测试名称")
额外注意事项
- 原视图代码中
home.html需要加单/双引号,否则会报语法错误;同时name变量需要提前定义,否则视图运行时会报错。 - 用
User.objects.create_user创建测试用户,能保证测试环境的独立性,不会受数据库现有数据影响。
内容的提问来源于stack exchange,提问作者dinesh
相关产品推荐
相关产品推荐

