3

我正在使用django-tokenapi来允许对使用 Django 作为后端的 Android 项目进行身份验证。该项目还有一个网络界面。

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

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

所以,理想情况下,它看起来像这样:

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

然而,这是行不通的。有没有更好的方法来做到这一点?或者正确的做法是拥有两个视图,一个是 webapp,一个是 Android,它们受到适当的装饰器的保护,然后导致相同的方法。

4

3 回答 3

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)

这解决了您提到的问题,同时仍然只维护实现视图的实际代码的一个副本。

于 2012-10-31T08:41:13.580 回答
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装饰器,如果用户登录或令牌有效,将允许访问视图。

于 2012-10-31T09:40:46.797 回答
0

可以在单个视图上使用多个装饰器。但在这种情况下,我认为您应该分开视图并单独应用装饰器。否则token_required,装饰器将尝试使用在使用浏览器发出的请求时不可用的令牌进行身份验证。

于 2012-10-31T08:24:46.373 回答