Python 如何用django编写自定义装饰器?

Python 如何用django编写自定义装饰器?,python,django,permissions,decorator,Python,Django,Permissions,Decorator,问题- @is_premium_user def sample_view: ....... ...... 我希望只有网站的高级用户才能访问某些视图。 如何在项目中的各种应用程序中使用此装饰器? 我是根据那篇博文写的 将其粘贴到python路径或“util”应用程序中的文件中,并将其导入到视图中: 例如 project_dir |_ app1 |_ app2 |_ utils |_ __init__.py |_ permreq.py fro

问题-

@is_premium_user
def sample_view:
          .......
          ......
我希望只有网站的高级用户才能访问某些视图。
如何在项目中的各种应用程序中使用此装饰器?

我是根据那篇博文写的

将其粘贴到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

您不必为此编写自己的装饰程序,因为Django中已经包含了它

还有一个片段()扩展了这个装饰器,它应该非常适合您的用例

如果你真的想写你自己的装饰,那么网上有很多


好吧,要(重新)使用decorator,只需将decorator放在路径上的一个模块中,您就可以从任何其他模块导入它。

请参阅django本身的示例:

您的特定示例可能只是“user_passes_test”的一个版本,其中测试将成为“premium”组的成员


要在任何地方使用,制作一个python包并从那里导入它。只要它在你的sys.path上,它就会被找到。

玩弄了上面的各种链接,无法让它们工作,然后遇到了我改编的这个非常简单的链接


使用
@wrapps
比像执行
wrapp那样手动重写要好。除此之外,它还确保包装函数与包装函数具有相同的名称


参见

多亏了arie,这个答案很有帮助,但对我不起作用

当我发现这个片段时,我让它正常工作:

这个解决方案对我有效:

助手功能

此功能的优点是可在其他地方重复使用,作为
用户的替代品。是否经过身份验证
。例如,它可以作为模板标记公开

def my_custom_authenticated(user):
    if user:
        if user.is_authenticated():
            return user.groups.filter(name=settings.MY_CUSTOM_GROUP_NAME).exists()
    return False
装饰师

我只是把它放在我的
视图.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):
    ...

下面是一个稍有不同的实现,它允许使用其他参数来指定验证失败时重定向到哪个页面,以及向最终用户显示哪个消息:

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


本指南帮助我理解了它:除了前面的答案之外,您还可以将它们写入您的模型中,并通过admin或django shelldef souk_required()对它们进行管理:“”需要至少一个传入组的用户成员身份。“”def拥有_souk(u):if u.经过身份验证():if bool(SoukUsers.objects.get(person=u)):return True return False(u)return user_通过测试(has_souk)它给出了这个错误-souk_required不接受任何参数(给定1个)Hm..我意外地对您的注释投了赞成票;-)嗯,您从函数定义中删除了预期的参数,因此收到了给定的错误。那么,创建一个“premiumusers”组并将您的用户添加到该组怎么样?然后你就可以按原样使用这个片段,只需输入你所在小组的名称即可。这不是你的错,这发生在我们当中最好的人身上;]。。。。无论如何,谢谢你,伙计。。。我欠你很多时间。这应该是公认的答案,竖起大拇指!我试图利用用户通过测试装饰器,但失败了,这节省了时间。@radtek I get
wrap()至少需要1个参数(给定0个)
。有什么线索可以解决吗?必须查看您的代码,但很可能您没有将请求传递给您正在装饰的函数。
@wrapps
方法仅适用于文档,因此您可以将其忽略,对吗?非常有效,谢谢:)
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):