django:django.utils.functional.SimpleLazyObject 的目的? [英] django: Purpose of django.utils.functional.SimpleLazyObject?

查看:15
本文介绍了django:django.utils.functional.SimpleLazyObject 的目的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,我将 request.user 分配给了一个名为 prior_user 的变量,然后基本上对用户进行了身份验证,然后检查是否 request.用户 !=prior_user.我希望它们不一样,并且 prior_user 应该包含 `AnonymousUser.令我惊讶的是,它们是一样的.

I ran into an issue where I assigned request.user to a variable called prior_user, then essentially authenticated the user, then checked to see if request.user != prior_user. I expected them not to be the same and that prior_user should contain `AnonymousUser. To my surprise, they were the same.

示例代码:

prior_user = request.user   # request object, obtained froma  view
authenticate_user(request)   # some function that authenticates
print prior_user.username != request.user.username   # returns False i.e.they are the same!

然后我发现prior_user实际上包含一个django.utils.functional.SimpleLazyObject的实例,所以我假设它是某种惰性查找类型的东西,即prior_user的值在实际使用之前不会被查找.查看源代码,我无法确认这一点.

I then discovered prior_user actually contains an instance of django.utils.functional.SimpleLazyObject so I assume it is some sort of lazy lookup type thing i.e. prior_user's value isn't looked up until actually used. Looking at the source code, I cannot confirm this.

任何有 Django 经验的人都可以告诉我发生了什么以及为什么需要它?

Anyone with django experience can tell me what is going on and why it is needed?

这让我有点震惊,因为通常的赋值语句并没有像我期望的那样工作,而且 Django 中还有什么是这样的?我也没有在 docs 中看到这一点.

This leaves me a little shaken, because the usual assignment statement doesn't work the way I expect and what else within Django acts like this? Nor did I see this described in the docs.

那么任何对 Django 具有超人类知识的人都可以提供一些清晰度吗?

So anyone with super human knowledge of django can provide some clarity?

推荐答案

auth 中间件为 request 添加了一个 user 属性,它是一个SimpleLazyObject 的实例.SimpleLazyObject,本身是LazyObject的子类.LazyObject 是,如实际代码所述:

The auth middleware adds a user attribute to request that is an instance of SimpleLazyObject. SimpleLazyObject, itself is a subclass of LazyObject. LazyObject is, as described by the actual code:

另一个类的包装器,可用于延迟包装类的实例化

A wrapper for another class that can be used to delay instantiation of the wrapped class

SimpleLazyObject 仅通过传入的方法设置该类(LazyObject 上的 _wrapped 属性),在本例中为 get_user.这是该方法的代码:

SimpleLazyObject merely sets that class (the _wrapped attribute on LazyObject) via a passed in method, in this case, get_user. Here's the code for that method:

def get_user(request):
    if not hasattr(request, '_cached_user'):
        request._cached_user = auth.get_user(request)
    return request._cached_user

这本身实际上只是 auth.get_user 的一个包装器,它启用了一种缓存机制.所以这里是最终运行的内容:

That in itself is really just a wrapper around auth.get_user, that enables a sort of caching mechanism. So here's what actually is eventually run:

def get_user(request):
    from django.contrib.auth.models import AnonymousUser
    try:
        user_id = request.session[SESSION_KEY]
        backend_path = request.session[BACKEND_SESSION_KEY]
        backend = load_backend(backend_path)
        user = backend.get_user(user_id) or AnonymousUser()
    except KeyError:
        user = AnonymousUser()
    return user

所以,这里真正发生的事情是 request.user 是模棱两可的,直到它实际用于某些事情为止.这很重要,因为它允许它根据当前身份验证状态进行调整.如果您在验证之前访问它的属性,它会返回一个实例 AnonymousUser,但是如果您验证然后访问它,它会返回一个 User<的实例/代码>.

So, all that's really going on here is that request.user is ambiguous until it's actually used for something. This is important, because it allows it to adapt depending on the current authentication status. If you access a property on it before you authenticate, it returns an instance AnonymousUser, but if you authenticate and then access it, it returns an instance of User.

这篇关于django:django.utils.functional.SimpleLazyObject 的目的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆