如何在Django中创建自定义装饰器?
我正在尝试在Django中创建一个自定义装饰器,但我找不到任何方法来实现。
# "views.py"
@custom_decorator
def my_view(request):
# .......
那么,我该如何在Django中创建这个装饰器呢?我应该把它放在哪里,这样我才能在我的Django项目的任何地方使用它呢?
8 个回答
6
感谢arie,这个答案帮了我很多,但对我来说并不管用。
当我找到这个代码片段时,我让它正常工作了:http://djangosnippets.org/snippets/983/
这个解决方案对我有效:
辅助函数
这个函数的好处是可以在其他地方重复使用,可以替代user.is_authenticated
。比如,它可以作为一个模板标签来使用。
def my_custom_authenticated(user):
if user:
if user.is_authenticated():
return user.groups.filter(name=settings.MY_CUSTOM_GROUP_NAME).exists()
return False
装饰器
我把这个放在我的views.py
文件的顶部,因为它很简短。
def membership_required(fn=None):
decorator = user_passes_test(my_custom_authenticated)
if fn:
return decorator(fn)
return decorator
使用它
@membership_required
def some_view(request):
...
88
我试了上面提到的各种链接,但都没能成功,后来发现了一个非常简单的例子,我做了一些调整。 http://code.activestate.com/recipes/498217-custom-django-login_required-decorator/
from functools import wraps
from django.http import HttpResponseRedirect
def authors_only(function):
@wraps(function)
def wrap(request, *args, **kwargs):
profile = request.user.get_profile()
if profile.usertype == 'Author':
return function(request, *args, **kwargs)
else:
return HttpResponseRedirect('/')
return wrap
使用 @wraps
比手动覆盖像 wrap.__doc__ = fn.__doc__
这种方式要好。这样做的好处之一是,它可以确保你的包装函数和被包装的函数拥有相同的名字。
62
你不需要自己写一个装饰器,因为 user_passes_test
已经在Django里提供了。
而且还有一个代码片段 (group_required_decorator
),它是对这个装饰器的扩展,应该很适合你的需求。
如果你真的想自己写一个装饰器,网上有很多不错的文档可以参考。
要使用这个装饰器,只需把你的装饰器放在一个模块里,并确保这个模块在你的路径中,这样你就可以从其他模块导入它。