2012-10-31 24 views
3

我使用django-tokenapi来允许对使用Django作为后端的Android项目进行身份验证。该项目还有一个Web界面。Django中有多个装饰器并且只使用一个

django-tokenapi使用@token_required修饰器来保护某些视图。 Django使用@login_required修饰器来保护某些视图。

我想只有一个视图受@login_required@token_required保护,因此它可以与webapp或Android应用程序一起使用。

所以,理想情况下,它应该是这样的:

@token_required 
@login_required 
def names_update(request): 
    .... 
    .... 

但是不起作用。有没有更好的方法来做到这一点?或者有两个视图是正确的,一个是webapp,另一个是适用于Android的视图,受适当的装饰器保护,然后导致相同的方法。

回答

0

可以在单个视图上使用多个装饰器。但在这种情况下,我认为你应该分开看法,并单独应用装饰者。否则token_required修饰器将尝试使用令牌进行认证,该令牌在使用浏览器进行的请求中不可用。

1

你可以尝试分配一个新的视图变量旧观点:

@token_required 
def names_update_token(request): 
    ... 

@login_required 
names_update_login = names_update_token 

这应该创建第二个观点叫names_update_login这仅仅是一个指向第一个效果,使代码保持相同。

编辑:

另一种思想,一个我都用过,就是创造一个更加“通用”的观点,并从各自的另一观点称之为:

def update_token(request): 
    ... 

@token_required 
def names_update_token(request): 
    update_token(request) 

@login_required 
def names_update_login(request): 
    update_token(request) 

这得到解决这个问题你提到的同时仍然只保留实现该视图的实际代码的单个副本。

+0

有趣的想法。当我尝试它时,它会抛出语法错误。我认为装饰者在它之后期待着一个功能。还有什么可能有用吗? – Alexis

+0

当面临类似的情况时,我简单地称另一个功能。 – zzzirk

+0

是的,这将工作。但它需要为每个功能维护两个urls.py设置。一个用于web应用程序,另一个用于Android应用程序。 – Alexis

1

不,根据你所描述的,如果可能的话,根本没有简单的方法来编写一个广义的OR装饰器。

然而,你可以写不正是你想要的一个新的装饰:

from functools import wraps 
from django.contrib.auth import authenticate, login 
from django.views.decorators.csrf import csrf_exempt 

def token_or_login_required(view_func): 
    """ 
    Decorator which ensures the user is either logged in or 
    has provided a correct user and token pair. 
    """ 

    @csrf_exempt 
    @wraps(view_func) 
    def _wrapped_view(request, *args, **kwargs): 
     user = request.REQUEST.get('user') 
     if user and user.is_authenticated: 
      return view_func(request, *args, **kwargs) 

     token = request.REQUEST.get('token') 

     if user and token: 
      user = authenticate(pk=user, token=token) 
      if user: 
       login(request, user) 
       return view_func(request, *args, **kwargs) 
     return HttpResponseForbidden() 
    return _wrapped_view 

这个装修结合了token_requiredlogin_required装饰,并允许访问视图或者如果用户登录,或者令牌有效。

+0

有没有办法做到这一点使用装饰代码的引用而不是实际的代码? – Alexis

+0

@AlexisK我不确定你引用的意思,但你可以把这个代码放在任何地方,然后把它导入并用作任何其他装饰器。 –

+0

我的意思是它是复制和粘贴来自其他地方的代码。有没有办法避免复制和粘贴代码?那样的话,如果事后在那些库中改变了,事情仍然会好的 – Alexis

相关问题