【问题标题】:Django Authorization - Return redirect within a function callDjango Authorization - 在函数调用中返回重定向
【发布时间】:2018-06-30 02:51:25
【问题描述】:

我正在添加一些自定义授权来验证登录用户是否有权访问我的应用程序的特定部分。它不漂亮,但它有效:

view_permissions = {
    'admin_list': {
        'school':{'userrole':['S','A'], 'usertype':[]},
        'class':{'userrole':['S','A'], 'usertype':[]},
        ' ... '
    },
    'delete_object': { ... },
    'edit_object': { ... },
    }
}

def check_permissions(request, viewname, objecttype):
    if(request.user.userrole in view_permissions[viewname][objecttype]['userrole'] or 
       request.user.usertype in view_permissions[viewname][objecttype]['usertype']
    ):
        return True
    else:
        return False

def delete_object(request, objecttype, objectid):

    # Redirect to home page if not authorized
    if(not check_permissions(request, 'delete_object', objecttype)):
        return redirect('wakemeup:index')

    # Otherwise, continue processing
    myobject.delete()
    ...

    return admin_list(request, objecttype)

我想要做的是将redirect 移动到check_permissions 函数内,如下所示:

def check_permissions(request, viewname, objecttype):
    if( <check permissions are valid> ):
        pass # Authorized: Do nothing and continue with caller view logic
    else:
        return redirect('wakemeup:index') # Unauthorized: redirect to home

def delete_object(request, objecttype, objectid):

    # Redirect to home page if not authorized
    check_permissions(request, 'delete_object', objecttype))

问题在于,check_permissions 函数内的重定向没有任何作用。如果我将return 添加到调用逻辑,它只会重定向:

def delete_object(request, objecttype, objectid):

    # Redirect to home page if not authorized
    return check_permissions(request, 'delete_object', objecttype))

我猜这与嵌套函数调用将其输出一直返回给原始调用者有关。但是有没有一种简单的方法可以让重定向从 check_permissions 函数中工作?

编辑

更新的函数——我必须通过 args[0] 访问 request 对象,但我可以通过 kwargs 访问我的其他变量。我想这是因为在表单中,请求对象只是在幕后传递,而不是作为参数。

def check_perm(view):
    viewname = view.__name__

    def view_wrapper(*args, **kwargs):

        objecttype = kwargs['objecttype']
        myuser = args[0].user

        if not (
            myuser.userrole in view_permissions[viewname][objecttype]['userrole'] or 
            myuser.usertype in view_permissions[viewname][objecttype]['usertype']
        ):
            # Invalid permission - redirect
            return redirect('wakemeup:index')

        # Valid permission - continue
        return view(*args, **kwargs)

    return view_wrapper

...

@check_perm
def delete_object(request, objecttype, objectid):
  ...

【问题讨论】:

  • 这基本上意味着重写整个视图代码,但是如果您切换到使用基于类的视图和PermissionRequiredMixin,这种事情会很多容易。
  • 是的,很早就决定绕过 Django 的 ORM。这是一个非常令人头疼的问题,所以我已经吸取了下次的教训。感谢您的建议。

标签: python django redirect authorization


【解决方案1】:

我认为函数装饰器是解决这个问题的完美方案。以下允许您检查条件(权限),如有必要,通过重定向劫持响应,如果没有,则继续正常查看响应:

from django.shortcuts import redirect

def check_permissions(view):
    view_name = view.__name__

    def view_wrapper(*args, **kwargs):
        # Check permissions here.
        if False or False or True:
            # Hijack response with a redirect if conditions not met.
            return redirect('wakemeup:index')

        # Conditions met, continue with normal response.
        return view(*args, **kwargs)

    return view_wrapper

@check_permissions
def delete_object(request, object_type, object_id):
    # Your normal view...
    return

另外,请注意它捕获视图名称的方式。在我看来更具活力。

【讨论】:

  • 这太棒了!我想这就是我一直在寻找的。但是,如何在 view_wrapper 中引用传递到视图中的变量(即请求、对象类型...)?我尝试通过kwargsargs 传递它们,但我无法引用它们。
  • 我让它工作了。见上面的编辑。谢谢!!这真是太棒了。
  • @ravioli 不客气!而且,根据您的编辑,我不确定您是否理解*args**kwargs。如果您不理解它们,我建议您阅读此stackoverflow.com/a/3394898/5971137
  • 我认为使用 **kwargs 可以让我直接引用函数中的关键字参数(即objecttype),而不必使用kwargs['objecttype']。不是这样吗?我应该以某种方式修改我的代码吗?
  • @ravioli 在函数定义的参数中列出**kwargs 允许您以字典的形式捕获任何以前未捕获的关键字参数。例如,如果函数的定义行是def view(foo=None, **kwargs),我可以像view(foo=1, hello=2, world=3)kwargs 一样调用它,在你的函数中,其值为{'hello': 2, 'world': 3}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
  • 1970-01-01
  • 2012-09-06
  • 2017-11-19
  • 2019-08-04
相关资源
最近更新 更多