使用混合方法加载站点可能对您有用。
def groupfinder(userid, request):
user = request.db.query(User).filter_by(id=userid).first()
if user is not None:
# somehow get the list of sites they are members
sites = user.allowed_sites
return ['site:%d' % s.id for s in sites]
class SiteFactory(object):
def __init__(self, request):
self.request = request
def __getitem__(self, key):
site = self.request.db.query(Site).filter_by(id=key).first()
if site is None:
raise KeyError
site.__parent__ = self
site.__name__ = key
site.__acl__ = [
(Allow, 'site:%d' % site.id, 'view'),
]
return site
我们将使用 groupfinder 将用户映射到主体。我们在这里选择仅将他们映射到他们拥有会员资格的网站。我们的简单遍历只需要一个根对象。它使用与设置创建的相同主体更新加载site
的内容。__acl__
groupfinder
您需要request.db
在 Pyramid Cookbook 中设置给定的模式。
def site_pregenerator(request, elements, kw):
# request.route_url(route_name, *elements, **kw)
from pyramid.traversal import find_interface
# we use find_interface in case we improve our hybrid traversal process
# to take us deeper into the hierarchy, where Site might be context.__parent__
site = find_interface(request.context, Site)
if site is not None:
kw['site_id'] = site.id
return elements, kw
Pregenerator 可以site_id
自动为您找到并添加到 URL。
def add_site_route(config, name, pattern, **kw):
kw['traverse'] = '/{site_id}'
kw['factory'] = SiteFactory
kw['pregenerator'] = site_pregenerator
if pattern.startswith('/'):
pattern = pattern[1:]
config.add_route(name, '/site/{site_id}/' + pattern, **kw)
def main(global_conf, **settings):
config = Configurator(settings=settings)
authn_policy = AuthTktAuthenticationPolicy('seekrit', callback=groupfinder)
config.set_authentication_policy(authn_policy)
config.set_authorization_policy(ACLAuthorizationPolicy())
config.add_directive(add_site_route, 'add_site_route')
config.include(site_routes)
config.scan()
return config.make_wsgi_app()
def site_routes(config):
config.add_site_route('site_users', '/user')
config.add_site_route('site_items', '/items')
我们在这里设置我们的应用程序。我们还将路线移动到一个可包含的功能中,这可以让我们更轻松地测试路线。
@view_config(route_name='site_users', permission='view')
def users_view(request):
site = request.context
然后我们的观点被简化了。只有当用户有权访问站点并且站点对象已经为我们加载时,它们才会被调用。
混合遍历
添加了一个自定义指令以使用包装器add_site_route
增强您的config
对象,该包装器add_route
将自动为路由添加遍历支持。当该路由匹配时,它将{site_id}
从路由模式中获取占位符并将其用作您的遍历路径(/{site_id}
这是我们根据遍历树的结构定义的路径)。
遍历发生在/{site_id}
第一步是找到树根的路径上(/
)。该路由被设置为使用SiteFactory
作为遍历路径的根执行遍历。此类被实例化为根,并__getitem__
使用路径中的下一个段 ( ) 中的键调用{site_id}
。然后,我们找到与该键匹配的站点对象,并在可能的情况下加载它。然后用__parent__
和更新站点对象__name__
以允许find_interface
工作。它还通过__acl__
稍后提到的提供权限进行了增强。
预发电机
每个路由都使用一个预生成器进行更新,该预生成器尝试Site
在遍历层次结构中查找请求的实例。如果当前请求未解析为基于站点的 URL,这可能会失败。然后,预生成器route_url
使用站点 ID 更新发送到的关键字。
验证
该示例显示了如何拥有将用户映射到指示该用户在“site:”组中的主体的身份验证策略。然后站点 ( request.context
) 被更新为具有一个 ACL,说明如果site.id == 1
“site:1”组中的某个人应该具有“查看”权限。然后users_view
将其更新为需要“查看”权限。HTTPForbidden
如果用户被拒绝访问视图,这将引发异常。如果需要,您可以编写一个异常视图有条件地将其转换为 404。
我回答的目的只是为了展示混合方法如何通过在后台处理 URL 的常见部分来使您的视图更好一些。HTH。