如何在Django中创建自定义装饰器?

jobtbby3  于 2022-11-18  发布在  Go
关注(0)|答案(8)|浏览(182)

我试图在Django中创建一个自定义的装饰器,但是我找不到任何方法。

# "views.py"

@custom_decorator 
def my_view(request):
    # .......

那么,我如何在Django中创建它呢?我应该把它放在哪里,以便我可以在Django项目的任何地方使用它?

1rhkuytd

1rhkuytd1#

玩了一下上面的各种链接,无法让它们工作,然后遇到了这个非常简单的一个,我改编. 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__更好。除此之外,它还确保 Package 函数与被 Package 函数具有相同的名称。

请参阅https://docs.python.org/2/library/functools.html

a64a0gku

a64a0gku2#

你不必为此编写自己的装饰器,因为user_passes_test已经包含在Django中了。
有一个代码片段(group_required_decorator)扩展了这个装饰器,它应该非常适合您的用例。
如果你真的想编写自己的装饰器,那么网上有很多good documentation
为了(重新)使用装饰器,只需将装饰器放在路径上的一个模块中,就可以从任何其他模块导入它。

oogrdqng

oogrdqng3#

多亏了阿里,这个答案帮了我很大的忙,但它对我不起作用。
当我找到这个代码片段时,我让它正常工作: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):
    ...
dpiehjr4

dpiehjr44#

看看django本身的例子:
http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/decorators.py
您的特定示例可能只是'user_passes_test'的一个版本,其中的测试将是'premium'组的成员资格。
要在任何地方使用,制作一个python包并从那里导入它。只要它在你的sys.path上,它就会被找到。

erhoui1w

erhoui1w5#

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
new9mtju

new9mtju6#

下面是一个稍有不同的实现,它允许使用附加参数来指定验证失败时要重定向到哪个页面,以及要向最终用户显示哪个消息:
第一个
这本指南帮助我度过了难关:https://elfsternberg.com/2009/11/20/python-decorators-with-arguments-with-bonus-django-goodness/与前面的答案并列

56lgkhnf

56lgkhnf7#

from django.contrib.auth.decorators import user_passes_test
from django.core.exceptions import PermissionDenied

def perm_group_required(group, login_url='/', raise_exception=False):
    def check_group(user):
        if user.groups.filter(name=group).exists():
            return True
        # In case the 403 handler should be called raise the exception
        if raise_exception:
            raise PermissionDenied
        return False
    return user_passes_test(check_group, login_url=login_url)

@perm_group_required('add_customer_group')
#group name="add_customer_group"
def employee_add_customer(request):
    ##logic
    ...
ni65a41a

ni65a41a8#

例如,通过下面的自定义装饰器@trantest()可以在事务中运行。* 您可以看到我的答案详细解释了自定义装饰器:

# "views.py"

from django.db import transaction
from django.http import HttpResponse

def tran(func): # Here
    def core(request, *args, **kwargs):
        with transaction.atomic():
            return func(request, *args, **kwargs)
    return core

@tran # Here
def test(request):
    person = Person.objects.all()
    print(person)
    return HttpResponse("Test")

相关问题