使“用户对象”可用作请求属性

这就是您:您的应用程序需要一个“用户对象”。 Pyramid 只愿意为你提供一个用户 id (通过 pyramid.security.authenticated_userid() )您不希望创建一个函数来接受一个请求对象并从您的域模型中返回一个用户对象,因为效率原因,并且您希望用户对象作为 request.user .

你试过用 NewRequest 订阅服务器将用户对象附加到请求,但 NewRequest 每个请求都会调用susbcriber,甚至静态资源也会调用susbcriber,这会让您感到困扰(它应该这样做)。

可以通过 pyramid.config.Configurator.add_request_method() API(在 Pyramid 1.4中引入;有关旧版本,请参见下文)。这允许您指定一个可调用的,它将在请求对象上可用,但在访问之前不会实际执行函数。这个函数的结果也可以缓存在每个请求中,以消除多次运行函数的开销(通过设置 reify=True ::

 1from pyramid.security import unauthenticated_userid
 2
 3def get_user(request):
 4    # the below line is just an example, use your own method of
 5    # accessing a database connection here (this could even be another
 6    # request property such as request.db, implemented using this same
 7    # pattern).
 8    dbconn = request.registry.settings['dbconn']
 9    userid = unauthenticated_userid(request)
10    if userid is not None:
11        # this should return None if the user doesn't exist
12        # in the database
13        return dbconn['users'].query({'id':userid})

以下是在配置代码中添加新请求属性的方法:

config.add_request_method(get_user, 'user', reify=True)

然后在视图代码中,您应该能够愉快地 request.user 获取与该请求相关的“用户对象”。它会回来 None 如果没有与请求关联的任何用户凭据,或者如果有与请求关联的用户凭据,但您的数据库中不存在该用户ID。无不当执行 authenticated_userid 完成(如果使用 NewRequest 用户)。

如果用户对象具有 groups 属性,返回具有 name 属性,可以将以下内容用作 callback (阿卡 groupfinder )大多数内置身份验证策略的参数。例如::

1from pyramid.authentication import AuthTktAuthenticationPolicy
2
3def groupfinder(userid, request):
4    user = request.user
5    if user is not None:
6        return [ group.name for group in request.user.groups ]
7    return None
8
9authn_policy = AuthTktAuthenticationPolicy('seekrITT', callback=groupfinder)

Pyramid 1.4之前

如果您使用的是1.3版,则可以按照与上面相同的步骤进行操作,除非使用此方法而不是 add_request_method ::

config.set_request_property(get_user, 'user', reify=True)

自 1.4 版本弃用: set_request_property()

之前 set_request_propertyadd_request_method ,可以使用类似的模式,但它需要 registering a new request factory 通过 set_request_factory() . 这是以同样的方式工作的,但是每个应用程序只能有一个请求工厂,因此对于任意属性来说,它不是非常可扩展的。

此方法的代码如下:

 1from pyramid.decorator import reify
 2from pyramid.request import Request
 3from pyramid.security import unauthenticated_userid
 4
 5class RequestWithUserAttribute(Request):
 6    @reify
 7    def user(self):
 8        # <your database connection, however you get it, the below line
 9        # is just an example>
10        dbconn = self.registry.settings['dbconn']
11        userid = unauthenticated_userid(self)
12        if userid is not None:
13            # this should return None if the user doesn't exist
14            # in the database
15            return dbconn['users'].query({'id':userid})

以下是在配置代码中使用新请求工厂的方法:

config.set_request_factory(RequestWithUserAttribute)