3


关于AuthenticationMiddleware,为什么 Django 1.3 会user在类级别处理属性,为什么在 1.4 中将其更改为实例属性?


这是从 1.3

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_request分配LazyUser()给类级别的user属性,这对我来说基本上意味着两件事:

  • HttpRequest( )在两个请求之间request.__class__存储了它的属性,因此未来的对象可以访问它。userrequest
  • 每当视图函数尝试访问request.user时,都会触发LazyUser对象的__get__方法并从请求的缓存或身份验证存储中返回一个用户对象。

我说得对吗?

另外,我在 1.4 中注意到了这两个主要变化:

  • SimpleLazyObject被分配给request,而不是它的类(因此,它是一个实例属性)。
  • LazyObject并且SimpleLazyObject不要定义(自定义)他们自己的__get__方法。

这样,什么时候get_user触发?
现在如何AuthenticationMiddleware在两个请求之间存储request.user,并覆盖Http的无状态?

4

1 回答 1

2

不,这两个版本是等效的。不过 1.4 版本更简单。

它过去是如何工作的

LazyUser对象实现了描述符协议

描述符理解起来有点复杂,但这里的总体思路是,虽然user是类属性,但访问request.userwoud call request.__class__.user.__get__(request),因此让__get__方法访问请求参数,它将用于返回绑定到请求的用户。

现在如何运作

user属性使用该SimpeLazyObject构造来实现相同的目标:如果不需要,避免加载所有用户机器。

至于何时get_user调用:

request.user例如,当您访问 上的属性时,将调用request.user.attr1then ,然后再request.user.__getattr__('attr1')调用request.user._setup(),最终将调用get_user

Django 如何创建有状态

通过使用会话。看看 django 的 session 中间件。

于 2013-03-02T12:30:55.927 回答