Python 如何将self对象传递给全局变量(Django视图)
我正在为基于Django的web应用程序编写功能。在各种基于类的视图方法中,如果用户在ban列表中,我会触发一些功能。由于我在多个视图中重复此比较,因此我决定将其转换为一个全局变量—在任何基于类的视图之外—因此:Python 如何将self对象传递给全局变量(Django视图),python,django,performance,Python,Django,Performance,我正在为基于Django的web应用程序编写功能。在各种基于类的视图方法中,如果用户在ban列表中,我会触发一些功能。由于我在多个视图中重复此比较,因此我决定将其转换为一个全局变量—在任何基于类的视图之外—因此: isbanned = HellBanList.objects.filter(condemned_id=self.request.user.id).exists() 不幸的是,我遇到了错误:未定义名称“self”,即self对象在基于类的视图之外不可用。对于request.user和u
isbanned = HellBanList.objects.filter(condemned_id=self.request.user.id).exists()
不幸的是,我遇到了错误:未定义名称“self”
,即self对象在基于类的视图之外不可用。对于request.user
和user
我也得到了类似的结果
是否有self.request.user
的变通方法可以用来计算这样一个全局变量(对经过身份验证和未经身份验证的用户都有效)?我的目标是只计算一次请求用户是否是hellban列表的一部分,然后在需要时使用该信息
或者,由于我在这里没有预见到的问题,我应该避免这样做吗?您不应该指望
请求
来执行查询。您应该使用参数user编写util功能,如下所示:
def is_banned(user):
return HellBanList.objects.filter(condemned_id=user.id).exists()
然后,当您需要检查时,请执行以下操作:
user_is_banned = is_banned(self.request.user)
首先,使用全局变量不是线程安全的。想象一下,两个请求同时被处理。第二个请求可能会在第一个请求完成之前覆盖
isbanked
,导致第一个请求被错误处理
若我是你们的话,我会写一篇文章,评估每个请求是否只禁止用户一次。然后将此信息存储在请求中:
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
之后定义中间件类,以便能够访问请求。用户
属性:
MIDDLEWARE_CLASSES = (
...
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'myapp.CalculateUserBannedMiddleware'
在代码的其余部分,您可以使用request.user\u banked
检查当前用户是否被禁止。这样,每个请求只计算一次标志
编辑: 如果延迟计算
user\u
,甚至可以使解决方案更智能。这样,对于不需要此标志的请求,您就不会有任何开销
实现延迟求值的一种方法是将对象与\uuuubool\uuuu
方法(Python 3)或\uuuuuuuuuuu非零方法(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)
谢恩,谢谢你的提示!问:我希望只执行一次“exists()”DB查询,然后在任何地方使用它。在您的解决方案中,这一目标会实现吗?还是每次我计算用户是否被禁止时,它都会执行一个新的DB查询?
?它会执行多次,但我相信执行exists()
是一种廉价的数据库操作。如果你真的想保存结果,你需要使用djangosession
或者内存中的工具,比如redis
。嘿,Dawid,你能不能修改一下你的答案中的一些完整性:?user
在你编写的中间件代码中没有定义。那应该是request.user
对吗?你是对的,应该是request.user
。我修好了。经过一番思考,我也想出了更聪明的解决办法。