繁体   English   中英

如何在Django中编写自己的装饰器?

[英]How can I write my own decorator in Django?

我的models.py文件如下:

from django.contrib.auth.models import User

class Shopkeeper(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    # ...


class Customer(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
# ...

我有一些视图,只有客户登录后才能访问,而店主则不能。 反之亦然。 如何为此类任务编写装饰器?

装饰器没有什么神奇的东西,它是一个将要装饰的函数(或类)作为输入并对其进行一些更改的函数。 如果我们查看login_required装饰器[GitHub]login_required看到:

 def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None): """ Decorator for views that checks that the user is logged in, redirecting to the log-in page if necessary. """ actual_decorator = user_passes_test( lambda u: u.is_authenticated, login_url=login_url, redirect_field_name=redirect_field_name ) if function: return actual_decorator(function) return actual_decorator 

因此,我们实际上可以简单地对user_passes_test装饰器进行特殊处理:

from django.contrib.auth.decorators import user_passes_test

def shopkeeper_required(function=None):
    def is_shopkeeper(u):
        return Shopkeeper.objects.filter(user=u).exists()
    actual_decorator = user_passes_test(is_shopkeeper)
    if function:
        return actual_decorator(function)
    else:
        return actual_decorator

def customer_required(function=None):
    def is_customer(u):
        return Customer.objects.filter(user=u).exists()
    actual_decorator = user_passes_test(is_customer)
    if function:
        return actual_decorator(function)
    else:
        return actual_decorator

然后,您可以例如将其实现为:

@login_required
@shopkeeper_required
def some_shopkeeper_view(request):
    # ...
    pass

@login_required
@customer_required
def some_customer_view(request):
    # ...
    pass

请注意,尽管在很多情况下,此@shopkeeper_required不会真正强制用户登录。

编辑

我们可以将其与@login_required合并(通过添加一个用作开关以默认打开或关闭此行为的参数),例如:

from django.contrib.auth.decorators import user_passes_test

def shopkeeper_required(function=None, login_required=True, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
    def is_shopkeeper(u):
        if login_required and not u.is_authenticated: return False
        return Shopkeeper.objects.filter(user=u).exists()
    actual_decorator = user_passes_test(
        is_shopkeeper,
        login_url=login_url,
        redirect_field_name=redirect_field_name
    )
    if function:
        return actual_decorator(function)
    else:
        return actual_decorator

def customer_required(function=None, login_required=True, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
    def is_customer(u):
        if login_required and not u.is_authenticated: return False
        return Customer.objects.filter(user=u).exists()
    actual_decorator = user_passes_test(
        is_customer,
        login_url=login_url,
        redirect_field_name=redirect_field_name
    )
    if function:
        return actual_decorator(function)
    else:
        return actual_decorator

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM