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

Django中用user_passes_test校验用户订阅有效性遇无订阅报错

解决Django订阅校验装饰器的问题

你的问题出在两个关键地方:一是捕获了错误的异常类型,二是没有正确调用订阅有效性检查的方法。以下是具体修正方案:

问题分析

  1. 异常捕获错误:当用户没有订阅时,访问user.subscription会抛出Subscription.DoesNotExist异常(而非user.DoesNotExist),你原代码的except块无法捕获这个错误,导致直接报错。
  2. 方法调用错误:代码里的user.subscription.is_subscription_valid没有加括号,这只是引用了方法对象而非执行方法,会导致无论订阅是否过期,这个值的布尔判断永远为True,完全失去校验作用。

修正后的校验函数

方案一:捕获正确的异常

from .models import Subscription  # 确保导入Subscription模型

def subscription_valid(user):
    # 超级用户直接跳过校验
    if user.is_superuser:
        return True
    try:
        # 调用订阅有效性检查方法(必须加括号执行)
        return user.subscription.is_subscription_valid()
    except Subscription.DoesNotExist:
        # 用户无订阅记录,返回False
        return False

方案二:先检查订阅是否存在

如果不想用异常捕获,也可以用hasattr先判断用户是否有订阅关联:

def subscription_valid(user):
    if user.is_superuser:
        return True
    # 先确认用户存在订阅记录
    if hasattr(user, 'subscription'):
        return user.subscription.is_subscription_valid()
    # 无订阅则返回False
    return False

装饰器的使用

将校验函数传入user_passes_test,指定重定向的仪表盘URL:

from django.contrib.auth.decorators import user_passes_test

def subscription_required(view_func):
    return user_passes_test(
        subscription_valid,
        login_url='/dashboard/'  # 替换为你的仪表盘实际URL
    )(view_func)

然后在需要校验的视图上使用装饰器:

@subscription_required
def premium_content_view(request):
    # 你的视图逻辑代码
    ...

额外优化建议

可以简化Subscription模型的is_subscription_valid方法,保持逻辑清晰:

def is_subscription_valid(self):
    return timezone.now() < self.expiration_date

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:10:32