我的应用程序中有以下装饰器,用于检查当前用户是否创建了任何位置对象,如果没有,则将其重定向到另一个URL。
def location_required(f):
def wrap(request, *args, **kwargs):
locations = Location.objects.filter(user=request.user)
if locations.count() == 0:
return HttpResponseRedirect("/")
return f(request, *args, **kwargs)
wrap.__doc__=f.__doc__
wrap.__name__=f.__name__
return wrap
我想为许多其他型号提供类似的功能。我希望能够将模型名称作为参数传递(而且可能也是重定向的URL),而不是创建多个装饰器。
这可能吗?我需要做出哪些改变?
非常感谢任何建议。
感谢。
答案 0 :(得分:2)
绝对有可能。它可能最终看起来像以下(未经测试的)代码:
def object_required(model_class, redirect_url):
def location_required(f):
def wrap(request, *args, **kwargs):
locations = model_class.objects.filter(user=request.user)
if locations.count() == 0:
return HttpResponseRedirect(redirect_url)
return f(request, *args, **kwargs)
wrap.__doc__=f.__doc__
wrap.__name__=f.__name__
return wrap
return location_required
我在这里所做的就是添加另一层包装。您的原始装饰者自定义了传入的函数f。我的外层自定义您的装饰器。你会以同样的方式使用它:
@object_required(Location, '/')
def my_view_func(request)
#your view code
答案 1 :(得分:2)
Gareth将现有装饰器包装在处理模型类和重定向url的另一个函数中的方法是正确的。我建议进行以下小改动:
exists()
代替将count()
与零django.utils.functional.wraps
更新换行功能,而不是手动设置__name__
和__doc__
。locations
变量名称错误,现在它可以是任何模型实例。 这给出了:
from django.utils.functional import wraps
def object_required(model_class, redirect_url="/"):
# model_class and redirect_url are available to all inner functions
def decorator(f):
# this is called with f, the function being decorated
def wrapper(request, *args, **kwargs):
# this is called each time the real function is executed
instances = model_class.objects.filter(user=request.user)
if not instances.exists():
return HttpResponseRedirect(redirect_url)
return f(request, *args, **kwargs)
return wraps(f)(wrapper)
return decorator
在视图中:
@object_required(Location, "/")
def my_view_function(request):
# your view code