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

如何批量测试Django视图是否应用LoginRequiredMixin或@login_required

如何批量测试Django视图的登录校验要求

当然可以!你完全可以编写一个批量测试用例,自动检查项目里除了少数例外之外的所有视图是否都应用了LoginRequiredMixin或者@login_required装饰器,这样后续新增视图时只要漏加校验,测试就会直接失败。

下面分享两种实用的实现方式:

方法一:遍历URL配置,检查视图的登录限制

这种方法会自动扫描你项目的URL路由,对每个对应的视图进行校验,你只需要指定不需要检查的视图列表即可。

完整代码示例

from django.test import TestCase
from django.urls import get_resolver
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User

class AllViewsLoginRequiredTest(TestCase):
    # 这里放不需要检查登录的视图(路径是视图的完整类/函数名)
    EXEMPT_VIEWS = [
        "django.contrib.auth.views.LoginView",
        "django.contrib.auth.views.LogoutView",
        # 加上你自己的例外视图,比如注册页、首页等
        "profiles.views.PublicHomeView"
    ]

    def setUp(self):
        self.user = User.objects.create(username='testuser')

    def test_all_views_require_login(self):
        # 获取项目所有URL解析器
        resolver = get_resolver()
        for url_pattern in resolver.url_patterns:
            # 处理包含命名空间的路由
            if hasattr(url_pattern, 'url_patterns'):
                self._check_nested_patterns(url_pattern.url_patterns)
            else:
                self._check_view(url_pattern.callback)

    def _check_nested_patterns(self, patterns):
        # 递归处理嵌套的URL配置
        for pattern in patterns:
            if hasattr(pattern, 'url_patterns'):
                self._check_nested_patterns(pattern.url_patterns)
            else:
                self._check_view(pattern.callback)

    def _check_view(self, callback):
        # 获取视图的完整标识符
        view_path = f"{callback.__module__}.{callback.__name__}"
        if view_path in self.EXEMPT_VIEWS:
            return

        # 检查基于类的视图是否继承了LoginRequiredMixin
        if hasattr(callback, 'view_class'):
            view_class = callback.view_class
            self.assertIn(LoginRequiredMixin, view_class.__bases__,
                          f"视图 {view_path} 未继承 LoginRequiredMixin")
        # 检查基于函数的视图是否应用了@login_required装饰器
        else:
            # 装饰器会把原始函数存放在__wrapped__属性里
            original_view = callback.__wrapped__ if hasattr(callback, '__wrapped__') else callback
            self.assertTrue(hasattr(original_view, '_decorated_function') and 
                            original_view._decorated_function is login_required,
                            f"视图 {view_path} 未使用 @login_required 装饰器")

    def test_unauthenticated_access_redirects(self):
        # 额外:可以选几个关键视图测试未登录访问是否重定向(可选)
        test_urls = [
            reverse("profiles:user_filter"),
            reverse("dashboard:index"),
            # 加上其他你想验证的URL
        ]
        for url in test_urls:
            response = self.client.get(url)
            self.assertRedirects(response, 
                                reverse("account_login") + f"?next={url}")

方法二:批量生成URL访问测试

如果你更关注“未登录访问是否会跳转到登录页”这个实际效果,可以用subTest为每个URL生成独立测试,哪个URL失败会直接明确显示:

from django.test import TestCase
from django.urls import reverse, get_resolver
from django.contrib.auth.models import User

class LoginRequiredViewsTest(TestCase):
    EXEMPT_URL_NAMES = [
        "account_login",
        "account_logout",
        "public_home",
        # 不需要检查的URL名称
    ]

    def setUp(self):
        self.user = User.objects.create(username='testuser')

    def test_views_require_login(self):
        resolver = get_resolver()
        # 获取所有已命名的URL
        named_urls = [(name, reverse(name)) for name in resolver.reverse_dict.keys() 
                      if isinstance(name, str)]
        
        for name, url in named_urls:
            if name in self.EXEMPT_URL_NAMES:
                continue
            with self.subTest(url_name=name):
                response = self.client.get(url)
                self.assertRedirects(response, 
                                    reverse("account_login") + f"?next={url}")

注意事项

  • 对于基于类的视图,记得把LoginRequiredMixin放在继承列表的最前面,避免和其他Mixin的优先级冲突。
  • 如果你用了自定义的登录装饰器,只需要修改检查逻辑,替换成你的装饰器判断条件就行。
  • 记得定期更新例外列表,确保不需要登录的视图被正确排除,避免误报。

这样一来,后续新增视图时只要漏加了登录校验,运行测试就会立刻报错,帮你提前把问题拦在上线前!

内容的提问来源于stack exchange,提问作者Milano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:03:00