对于我的很多(但不是全部)视图,我必须进行一些验证,以确保登录的用户有权访问他们尝试访问的对象。对于30多个视图,我有以下代码:
def whatever_view_name(request, id, access_id):
check = Access.objects.filter(user=request.user, id=access_id)
if check:
access_object = check[0]
else:
return redirect(reverse("create_new_access_object"))
.... and now my view-specific code will follow ...
因此,我需要检查该特定用户是否存在特定数据库记录(访问)。这段代码被重复了很多,似乎不正确。我一直在考虑使用中间件,但是有两个问题:a)我需要在视图中使用此对象(请参见变量access_object
,所以我担心如果将其放入,则必须对其进行两次查询中间件),并且b)我始终不需要这样做,所以我想知道如何仅针对某些视图运行它,如果这是中间件,则不是全部运行。
有什么想法吗?
答案 0 :(得分:2)
我能想到的一种方法是使用继承。我们可以将常见的内容重构为一个超级视图类,然后在子视图类中进行扩展。
类似这样的东西:
我们可以有一个这样的超类
class AccessVerifiedView(View):
def get(self, request, *args, **kwargs):
check = Access.objects.filter(user=request.user, id=kwargs["access_id"])
if check:
access_object = check[0]
self.verified_get(access_object)
else:
return redirect(reverse("create_new_access_object"))
def verified_get(self, access_object):
raise NotImplementedError
然后我们可以在我们的视图中扩展该类及其用途。
class MyView(AccessVerifiedView):
def verified_get(self, access_object):
return access_object
这种方法更具可读性。看到代码的任何人都可以看到超类并了解代码流。
其他几种方法是
答案 1 :(得分:2)
您可以为此编写装饰器:
from functools import wraps
def check_access(function):
@wraps(function)
def wrap(request, id, access_id, *args, **kwargs):
check = Access.objects.filter(user=request.user, id=access_id)
if check.exists():
return function(request, id, access_id, *args, **kwargs)
else:
return redirect(reverse("create_new_access_object"))
return wrap
# usage
@check_access
def whatever_view_name(request, id, access_id):
return ...