假设我的系统有一些公共页面(非认证用户和登录用户都可以查看)和其他只有登录用户可以查看的页面.
我希望模板为这两类页面中的每一类显示略微不同的内容.@login_required视图装饰器始终用于只有登录用户可以查看的视图.但是,我的模板需要知道是否在从中调用模板的视图上使用了此装饰器.
请记住,我不关心用户是否登录公共页面.我关心的是一般公众是否可以查看某个页面,并且没有@login_required装饰器会告诉我这一点.
任何人都可以告诉我模板如何知道模板调用的视图上是否使用了特定的装饰器?
是的,这是可能的,但不是非常简单明了.复杂的因素是Django的login_required
装饰器实际上通过了两个级别的间接(一个动态函数和另一个装饰器),最终到达django.contrib.auth.decorators._CheckLogin,这是一个带__call__
方法的类.
假设您有一个非django,花园式装饰功能,如下所示:
def my_decorator(func): def inner(): return func() return inner @my_decorator def foo(): print foo.func_name # results in: inner
检查函数foo
是否已被包装可以像检查函数对象的名称一样简单.您可以在函数内执行此操作.该名称实际上是最后一个包装函数的名称.对于更复杂的情况,inspect
如果您正在寻找特定的东西,可以使用该模块从当前帧向上走外框.
在Django的情况下,然而,事实上,装饰实际上是一个实例_CheckLogin
级意味着该函数是不是一个真正的功能,因此没有func_name
财产:试图在上面的代码将引发异常.
django.contrib.auth.decorators._CheckLogin
但是,查看源代码_CheckLogin
会显示该实例将具有login_url
属性.这是一个非常简单的测试方法:
@login_required def my_view(request): is_private = hasattr(my_view, 'login_url')
因为_CheckLogin
也被用来实现其他身份验证的装饰,这种做法也工作了permission_required
,等我从来没有真正有需要使用这一点,但是,所以我真的不能,你应该寻找什么,如果你有意见围绕单个视图的多个装饰器...我想(练习留给读者)(检查帧堆栈?).
然而,正如未经考虑的编辑建议,我会说检查功能本身,看看它是否像这样包裹让我感到有点狡猾.您可以想象当一个新的开发人员作为其他装饰器上的slaps进入项目时,等待发生的各种不可预测的行为.事实上,你也暴露了django框架本身的变化......等待发生的安全风险.
我会推荐Van Gale的方法,因为它是明确的,因此是一个更强大的实现.