如何将self对象传递给Global变量(Django视图)

时间:2015-11-07 17:28:59

标签: python django performance

我正在为基于Django的网络应用编写hellban功能。在各种基于类的视图方法中,如果用户处于禁止列表,我会触发一些功能。由于我在几个视图中重复这种比较,因此我决定将其转换为全局变量 - 在任何基于类的视图之外 - 因此:

isbanned = HellBanList.objects.filter(condemned_id=self.request.user.id).exists()

不幸的是,我遇到了错误:name 'self' is not defined,即自我对象在基于类的视图之外不可用。我也得到request.useruser的类似结果。

我是否可以使用self.request.user来解决这样一个全局变量(适用于经过身份验证和未经身份验证的用户)?我的目标是仅计算ONCE请求用户是否是hellban列表的一部分,然后在需要的地方使用该信息。

或者,由于我在这里没有预见到的问题,我应该避免这样做吗?

2 个答案:

答案 0 :(得分:2)

首先,拥有全局变量不是线程安全的。想象一下,同时处理了两个请求。第二个可以在第一个完成之前覆盖isbanned,导致第一个请求被错误处理。

如果我是你,我会写middleware class来评估用户是否每次请求只被禁止一次。然后将此信息存储在请求中:

class CalculateUserBannedMiddleware(object):

    def process_request(self, request):
        request.user_banned = HellBanList.objects.filter(condemned_id=request.user.id).exists()

需要在django.contrib.auth.middleware.AuthenticationMiddleware之后定义中间件类才能访问request.user属性:

MIDDLEWARE_CLASSES = (
    ...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'myapp.CalculateUserBannedMiddleware'

在其余代码中,您可以使用request.user_banned来检查当前用户是否被禁止。这样,每个请求只计算一次标志。

编辑:

如果懒惰地计算user_banned,您甚至可以使解决方案变得更加智能。这样,对于不需要此标志的请求,您就没有任何开销。

实现延迟评估的一种方法是使用带有__bool__方法(Python 3)或__nonzero__方法(Python 2)的对象。

Python 3的示例实现:

class LazyUserBannedFlag(object):

    user_banned = None

    def __init__(self, request):
        self.request = request

    def __bool__(self):
        if self.user_banned is None:
            user_id = self.request.user.id
            self.user_banned = HellBanList.objects.filter(condemned_id=user_id).exists()
        return self.user_banned


class CalculateUserBannedMiddleware(object):

    def process_request(self, request):
        request.user_banned = LazyUserBannedFlag(request)

答案 1 :(得分:1)

您不应指望request进行查询。您应该使用参数作为用户编写一个util函数,如下所示:

def is_banned(user):
    return HellBanList.objects.filter(condemned_id=user.id).exists()

然后当您需要检查时,请执行:

user_is_banned = is_banned(self.request.user)