Django测试登录视图报HttpRequest无user属性的AttributeError如何解决
问题原因
Django 触发 user_logged_in 信号时,尚未将完成登录的用户对象绑定到请求对象上,此时直接访问 request.user 会触发属性不存在的报错。另外报错栈显示实际触发的函数名为 on_user_logged_out,与你定义的信号处理函数名 on_user_logged_in 不一致,属于笔误,记得同步修正避免其他逻辑异常。
解决方案
方案1(推荐):直接使用信号传入的用户参数
user_logged_in 信号触发时已经默认将当前登录用户作为参数传递给处理函数,无需从请求中二次取值,直接修改信号代码即可:
@receiver(user_logged_in) def on_user_logged_in(sender, request, user, **kwargs): messages.add_message( request, messages.INFO, f"{user.username} successfully logged in!", )
修改后无需调整测试代码,线上业务逻辑和单元测试都可以正常运行。
方案2:单元测试时临时禁用信号
如果暂时不想调整现有信号逻辑,也可以在测试用例中临时断开信号连接规避报错:
from django.contrib.auth.signals import user_logged_in from accounts.views import on_user_logged_in class LoginPageTests(TestCase): username = "newuser" email = "newuser@email.com" password = "averydeifficultpasswordtobreak" def setUp(self): # 测试前断开登录信号连接 user_logged_in.disconnect(receiver=on_user_logged_in) def tearDown(self): # 测试结束后重新连接信号,避免影响其他测试用例 user_logged_in.connect(receiver=on_user_logged_in) # 剩余测试代码保持不变 def test_login_page_status_code(self): response = self.client.get("/accounts/login/") self.assertEqual(response.status_code, 200) def test_view_url_by_name(self): response = self.client.get(reverse("login")) self.assertEqual(response.status_code, 200) def test_view_uses_correct_template(self): response = self.client.get(reverse("login")) self.assertTemplateUsed(response, "registration/login.html") def test_login_form(self): new_user = get_user_model().objects.create_user(self.username, self.email) new_user.set_password(self.password) new_user.save() logged_in = self.client.login(username=self.username, password=self.password) self.assertEqual(logged_in, True)
内容的提问来源于stack exchange,提问作者Farhan M.
相关产品推荐
相关产品推荐

