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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:15:33