【问题标题】:custom decorator for class viewsets类视图集的自定义装饰器
【发布时间】:2016-09-30 07:27:42
【问题描述】:

我有这样的视图集

class NeProjectsViewSet(viewsets.ViewSet):

   def list(self, request,org_unique_id):
       ''' something '''

   def create(self, request,org_unique_id):
       ''' something '''

   def retrieve(self):
       ''' something '''

   def update(self, request, pk):
       ''' something '''

   def partial_update(self, request):
       ''' something '''

   def destroy(self, request):
       ''' something '''

我有这样的方法

def check_session(self,request):
    current_datetime = datetime.now()
    if ('last_login' in request.session):
        last = (current_datetime - datetime.strptime(request.session['last_login'], "%Y-%m-%d %H:%M:%S.%f")).seconds
        if last > base.SESSION_IDLE_TIMEOUT:
            del request.session['token']
            raise ValueError('Session Expired')
    else:
        request.session['last_login'] = str(current_datetime)
    return (request.session['token'] == request.META['HTTP_AUTHORIZATION'])

为每个请求验证会话,为此我需要在视图集中的每个方法之前调用此方法。我在某处读到写自定义装饰器是更好的方法,所以如何为我的视图集实现自定义装饰器以检查请求的会话

【问题讨论】:

  • 在这种情况下,add custom middleware 很可能会更方便
  • 我只想验证特定 api 的会话,而不是每个 api,如果我们可以用中间件做到这一点,你能提供代码如何做到这一点

标签: python django python-decorators


【解决方案1】:

假设您使用的是 DRF。

我认为你走错了方向。如果这是您的权限层的一部分,您应该将自定义权限类添加到您的视图集

http://www.django-rest-framework.org/api-guide/permissions/

from rest_framework import permissions

class ValidateSession(permissions.BasePermission):
    """
    Validate session expiration
    """

    def has_permission(self, request, view):
        current_datetime = datetime.now()
        if ('last_login' in request.session):
            last = (current_datetime - datetime.strptime(request.session['last_login'], "%Y-%m-%d %H:%M:%S.%f")).seconds
            if last > base.SESSION_IDLE_TIMEOUT:
                del request.session['token']
                return False
        else:
            request.session['last_login'] = str(current_datetime)
        return (request.session['token'] == request.META['HTTP_AUTHORIZATION'])

然后像这样添加

class NeProjectsViewSet(viewsets.ViewSet):
    permission_classes = (ValidateSession,)
    ...

假设您使用的是普通 django

from django.contrib.auth.mixins import AccessMixin

class ValidateSessionMixin(AccessMixin):
    """
    Validate session
    """
    def has_permission(self):
        current_datetime = datetime.now()
        request = self.request
        if ('last_login' in request.session):
            last = (current_datetime - datetime.strptime(request.session['last_login'], "%Y-%m-%d %H:%M:%S.%f")).seconds
            if last > base.SESSION_IDLE_TIMEOUT:
                del request.session['token']
                return True
        else:
            request.session['last_login'] = str(current_datetime)
        return (request.session['token'] == request.META['HTTP_AUTHORIZATION'])

    def dispatch(self, request, *args, **kwargs):
        if not self.has_permission():
            return self.handle_no_permission()
        return super(ValidateSessionMixin, self).dispatch(request, *args, **kwargs)

然后像这样应用这个 mixin

class NeProjectsViewSet(ValidateSessionMixin, viewsets.ViewSet):
    ...

【讨论】:

  • 我看到请求在 has_permission 函数中。如果我想为读取或写入应用不同的权限,我是否只需检查请求以查看它是 GET 还是 PUT?我没有看到根据不同规则验证读取或写入之间的明显区别(除了允许所有读取,我显然不希望这样做,除非我误读了该文档链接)。
  • @KennyOstrom 你想要这个在 drf 还是 django 中?
  • 这是一个 django 应用程序,带有 rest_framework.viewsets.ViewSet 和一些关于谁可以看到哪些内容的自定义规则,我正在添加一个必须检查附加权限的写入接口(实现视图集的创建)根据 request.user
  • @KennyOstrom 我建议为此创建一个单独的问题
猜你喜欢
  • 2014-06-07
  • 2016-08-16
  • 2013-02-06
  • 2011-08-07
  • 1970-01-01
  • 2019-06-27
  • 1970-01-01
  • 2020-09-04
相关资源
最近更新 更多