gpt4 book ai didi

python - 如何以优雅的方式处理复杂的 URL?

转载 作者:太空狗 更新时间:2023-10-29 22:27:18 25 4
gpt4 key购买 nike

我正在编写一个管理网站,它控制多个具有相同程序和数据库架构但内容不同的网站。我设计的网址是这样的:

http://example.com/site                 A list of all sites which under control
http://example.com/site/{id} A brief overview of select site with ID id
http://example.com/site/{id}/user User list of target site
http://example.com/site/{id}/item A list of items sold on target site
http://example.com/site/{id}/item/{iid} Item detailed information
# ...... something similar

如您所见,几乎所有 URL 都需要 site_id。在几乎所有 View 中,我都必须做一些常见的工作,比如使用 site_id 查询针对数据库的站点模型。此外,每当我调用 request.route_path 时,我都必须传递 site_id。

那么...有什么方法可以让我的生活更轻松吗?

最佳答案

使用混合方法加载网站可能对您有用。

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 将用户映射到主体。我们在这里选择只将他们映射到他们拥有成员(member)资格的网站。我们简单的遍历只需要一个根对象。它使用 __acl__ 更新加载的 site,该 __acl__ 使用 groupfinder 设置创建的相同原则。

您需要在 Pyramid Cookbook 中设置 request.db 给定模式。

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,这可能会失败。预生成器然后使用站点 ID 更新发送到 route_url 的关键字。

身份验证

该示例展示了如何拥有一个身份验证策略,该策略将用户映射到指示该用户位于“site:”组中的主体。该站点 (request.context) 然后更新为具有一个 ACL,说明如果 site.id == 1 “site:1” 组中的某个人应该具有“查看”权限。 users_view 然后更新为需要“查看”权限。如果拒绝用户访问 View ,这将引发 HTTPForbidden 异常。如果需要,您可以编写异常 View 以有条件地将其转换为 404。

我回答的目的只是为了展示混合方法如何通过在后台处理 URL 的公共(public)部分来使您的 View 更好一些。 HTH.

关于python - 如何以优雅的方式处理复杂的 URL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13193442/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com