Django - AuthenticationMiddleware 设置 request.user

3
关于 AuthenticationMiddleware,为什么 Django 1.3 在类级别上处理了 user 属性, 而在 1.4 中将其更改为实例属性?
class LazyUser(object):
    def __get__(self, request, obj_type=None):
        if not hasattr(request, '_cached_user'):
            from django.contrib.auth import get_user
            request._cached_user = get_user(request)
        return request._cached_user


class AuthenticationMiddleware(object):
    def process_request(self, request):
        request.__class__.user = LazyUser()
        return None


而这是从1.4开始的

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


class AuthenticationMiddleware(object):
    def process_request(self, request):
        assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."

        request.user = SimpleLazyObject(lambda: get_user(request))
        # SimpleLazyObject inherits from LazyObject

在1.3中,我理解process_requestLazyUser()分配给类级别的user属性。这对我来说基本意味着两件事:
  • HttpRequest类(request.__class__)在两个请求之间存储了它的user属性,因此未来的request对象可以访问它。
  • 每当视图函数尝试访问request.user时,触发LazyUser对象的__get__方法,并返回一个用户对象,该对象要么来自请求的缓存,要么来自授权存储。
我理解得正确吗? 此外,我注意到在1.4中有两个主要的更改:
  • SimpleLazyObject被分配给request,而不是它的类(因此,它是一个实例属性)。
  • LazyObjectSimpleLazyObject不定义(自定义)它们自己的__get__方法。
这样做后,什么时候会触发get_user
AuthenticationMiddleware现在如何在两个请求之间存储request.user,并覆盖Http的无状态性?

1
Session 中间件是让你“覆盖 HTTP 无状态性”的中间件,基本上可以通过使用会话 cookie 实现。在这里查看它:https://github.com/django/django/blob/master/django/contrib/sessions/middleware.py - Thomas Orozco
1个回答

2
不,这两个版本是等效的。虽然1.4版本更简单。
它过去是如何工作的:
LazyUser对象实现了描述符协议。描述符有点复杂,但总体思路是,尽管user是一个类属性,访问request.user会调用request.__class__.user.__get__(request),从而让__get__方法访问请求参数,并使用其返回绑定到请求的用户。
现在它是如何工作的: user属性使用SimpleLazyObject构造来实现相同的目标:如果不需要加载所有用户机制,则避免加载它们。
至于什么时候调用get_user:
当您访问request.user上的属性,例如request.user.attr1时,将调用request.user.__getattr__('attr1'),这将进而调用request.user._setup(),最终调用get_user

Django如何创建状态性

通过使用会话。请查看Django的会话中间件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接