【发布时间】:2011-07-25 01:25:19
【问题描述】:
问题-
@is_premium_user
def sample_view:
.......
......
我希望只有网站的高级用户才能访问某些视图。
以及如何在我的项目中的各种应用程序中使用这个装饰器?
【问题讨论】:
标签: python django permissions decorator
问题-
@is_premium_user
def sample_view:
.......
......
我希望只有网站的高级用户才能访问某些视图。
以及如何在我的项目中的各种应用程序中使用这个装饰器?
【问题讨论】:
标签: python django permissions decorator
玩弄了上面的各种链接,但无法让它们工作,然后遇到了我改编的这个非常简单的链接。 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__)更好。除此之外,它还确保您的包装函数与被包装函数的名称相同。
【讨论】:
wrap() takes at least 1 argument (0 given)。有什么线索可以解决吗?
@wraps 方法仅适用于文档,因此您可以省略它,对吧?
您不必为此编写自己的装饰器,因为 user_passes_test 已经包含在 Django 中。
还有一个 sn-p (group_required_decorator) 扩展了这个装饰器,它应该非常适合您的用例。
如果你真的想写自己的装饰器,那么网上有很多good documentation。
好吧,要(重新)使用装饰器,只需将装饰器放在路径上的一个模块中,您就可以从任何其他模块导入它。
【讨论】:
感谢arie,这个答案帮了我很大的忙,但它对我不起作用。
当我找到这个 sn-p 时,我让它正常工作: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):
...
【讨论】:
查看 django 本身的示例:
http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/decorators.py
您的特定示例可能只是“user_passes_test”的一个版本,其中测试将成为“高级”组的成员。
要在任何地方使用,请制作一个 python 包并从那里导入它。只要它在您的 sys.path 上,就会被找到。
【讨论】:
http://www.makina-corpus.org/blog/permission-required-decorator-django
我是根据那篇博文建立的。
将其粘贴到 python 路径中的文件或“util”应用程序中并将其导入视图:
例如
project_dir
|_ app1
|_ app2
|_ utils
|_ __init__.py
|_ permreq.py
from util.permreq import permission_required
@permmission_required('someapp.has_some_perm', template='denied.html')
def some_view(request):
blah blah
【讨论】:
这是一个稍微不同的实现,它允许附加参数以指定在验证失败时重定向到哪个页面,以及向最终用户显示哪个消息:
from functools import wraps
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from core.helpers.flash import send_flash_error
def lender_only(redirect_to='plateforme.views.vue_login', error_flash_message=None):
def inner_render(fn):
@wraps(fn) # Ensure the wrapped function keeps the same name as the view
def wrapped(request, *args, **kwargs):
if request.context.user.is_authenticated and request.context.user.is_lender:
return fn(request, *args, **kwargs)
else:
if error_flash_message:
send_flash_error(request, error_flash_message) # Replace by your own implementation
return HttpResponseRedirect(reverse(redirect_to))
return wrapped
return inner_render
# Usage:
@lender_only('vitrine.views.projets', {'message': "Oops, can't go there."})
def render_page_index(request):
本指南帮助我完成了它:https://elfsternberg.com/2009/11/20/python-decorators-with-arguments-with-bonus-django-goodness/ 以及之前的答案
【讨论】: