Django单元测试报错:'AnonymousUser'对象无'is_merchant'属性
问题描述
我编写了如下Django单元测试代码:
class CampaignModelTests(TestCase): # https://docs.djangoproject.com/en/4.1/topics/testing/advanced/ def setUp(self): # create some test campaigns shop = Shop.objects.create(name='Test Shop') self.factory = RequestFactory() self.user = User.objects.create(shop_username='testuser', shop=shop) self.merchant = User.objects.create(username='merchant', password='merchant123', is_merchant=True, shop=shop) self.campaign = Campaign.objects.create(name='Test Campaign', shop=shop) def test_campaign_creation(self): request = self.factory.get(reverse('create-campaign'), { 'name': 'Test Campaign -1', 'shop': Shop(name='Test Shop').sid }) request.user = self.merchant print('request.user: ', request.user.is_merchant) response = CampaignCreate.as_view()(request) self.assertEqual(response.status_code, 200)
运行时出现如下错误:
return request.user.is_merchant or request.user.is_superuser AttributeError: 'AnonymousUser' object has no attribute 'is_merchant'
我还尝试使用self.client进行测试,代码如下,但仍出现相同错误:
self.client.force_login(self.merchant) # send a request to the view response = self.client.post(reverse('create-campaign'), { 'name': 'Test Campaign -1', 'shop': Shop(name='Test Shop').sid }) self.assertEqual(response.status_code, 200)
解决方案
核心问题是自定义User模型的is_merchant字段未被认证系统正确识别,导致视图中访问request.user.is_merchant时,实际拿到的是未关联自定义属性的AnonymousUser对象。以下是具体修复步骤:
确认自定义User模型配置
检查settings.py中是否正确指定了自定义用户模型,确保指向包含is_merchant字段的User模型:AUTH_USER_MODEL = 'your_app_name.User'修复用户创建逻辑
创建self.merchant时,不能直接明文存储密码,需用set_password生成哈希密码:# 修改setUp中的merchant创建代码 self.merchant = User.objects.create(username='merchant', is_merchant=True, shop=shop) self.merchant.set_password('merchant123') self.merchant.save()同时将setUp中的
shop赋值给self.shop,避免后续使用未保存的Shop实例:self.shop = Shop.objects.create(name='Test Shop')RequestFactory测试修复
直接赋值request.user无法触发完整认证流程,需手动添加会话和认证中间件处理,且使用已保存的self.shop.sid:from django.contrib.auth.middleware import AuthenticationMiddleware from django.contrib.sessions.middleware import SessionMiddleware def test_campaign_creation(self): request = self.factory.get(reverse('create-campaign'), { 'name': 'Test Campaign -1', 'shop': self.shop.sid }) # 添加会话中间件 session_middleware = SessionMiddleware(lambda req: None) session_middleware.process_request(request) request.session.save() # 添加认证中间件 auth_middleware = AuthenticationMiddleware(lambda req: None) auth_middleware.process_request(request) # 绑定用户 request.user = self.merchant response = CampaignCreate.as_view()(request) self.assertEqual(response.status_code, 200)Client测试修复
确保请求参数使用已保存的self.shop.sid:def test_campaign_creation_with_client(self): self.client.force_login(self.merchant) response = self.client.post(reverse('create-campaign'), { 'name': 'Test Campaign -1', 'shop': self.shop.sid }) self.assertEqual(response.status_code, 200)视图权限校验优化
在视图中先判断用户是否认证,再访问自定义属性,避免报错:# 视图中的权限校验逻辑 if request.user.is_authenticated: if request.user.is_merchant or request.user.is_superuser: # 业务逻辑处理 else: # 无权限处理 else: # 未认证用户处理
内容的提问来源于stack exchange,提问作者snake_case
相关产品推荐
相关产品推荐

