jjzjj

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

coder 2023-08-26 原文

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

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/

有关python - 如何以优雅的方式处理复杂的 URL?的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  5. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  6. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  7. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

  8. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  9. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

  10. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

随机推荐