使用Traversal制作子应用程序的最佳方法

时间:2012-07-22 14:53:37

标签: python pyramid traversal

好的,所以我有我的应用程序,它接受来自根/的请求几乎所有东西都在使用遍历。

但我想在该网站上做一个休息api。

所以我有两个选择。我要么在两个不同的应用程序中将其分开,并将该休息应用程序放到:rest.site.com,或者我可以将其移至site.com/rest/*traversal

如果我正在做“/ rest / *遍历”,我想我必须添加一个名为rest_traversal的路由,其中​​遍历路径为*traversal,路由为/rest/*traversal }。我为管理页面做了一次。

我想知道是否有最干净的方法。我尝试使用virtual_root,但据我所知,virtual_root实际上已添加到遍历路径中。

喜欢virtual_root = /cms和请求/fun会创建以下路径/cms/fun

另一方面,我希望/cms/fun变成/fun

2 个答案:

答案 0 :(得分:3)

我知道这已经得到了解答,但是如果有人来到这里寻找另一种可能的方法来制作“子应用程序”并在金字塔中使用它们,我想指出一些有趣的事情可以用{{3}完成}

"""
example of wsgiapp decorator usage
http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/api/wsgi.html
"""

from pyramid.wsgi import wsgiapp2, wsgiapp
from pyramid.config import Configurator
from webob import Request, Response
import pprint

# define some apps


def wsgi_echo(environ, start_response):
    """pretty print out the environ"""
    response = Response(body=pprint.pformat({k: v for k, v in environ.items()
                                             if k not in ["wsgi.errors",
                                                          "wsgi.input",
                                                          "SCRIPT_NAME"]}))
    return response(environ, start_response)


print Request.blank("/someurl").send(wsgi_echo).body


# convert wsgi app to a pyramid view callable
pyramid_echo = wsgiapp(wsgi_echo)
pyramid_echo_2 = wsgiapp2(wsgi_echo)

# wire up a pyramid application

config = Configurator()
config.add_view(pyramid_echo, name="foo")  # /foo
config.add_view(pyramid_echo, name="bar")  # /bar
config.add_view(pyramid_echo_2, name="foo_2")  # /foo
config.add_view(pyramid_echo_2, name="bar_2")  # /bar
pyramid_app = config.make_wsgi_app()

#call some urls
foo_body = Request.blank("/foo").send(pyramid_app).body
bar_body = Request.blank("/bar").send(pyramid_app).body
foo_body_2 = Request.blank("/foo_2").send(pyramid_app).body
bar_body_2 = Request.blank("/bar_2").send(pyramid_app).body

# both should be different because we arrived at 2 different urls
assert foo_body != bar_body, "bodies should not be equal"

# should be equal because wsgiapp2 fixes stuff before calling
# application in fact there's an additional SCRIPT_NAME in the
# environment that we are filtering out
assert foo_body_2 == bar_body_2, "bodies should be equal"

# so how to pass the path along? like /foo/fuuuu should come back
# /fuuuu does it
foo_body = Request.blank("/foo_2/fuuuu").send(pyramid_app).body
assert "'/fuuuu'," in foo_body, "path didn't get passed along"


# tldr: a wsgi app that is decorated with wsgiapp2 will recieve data
# as if it was mounted at "/", any url generation it has to do should
# take into account the SCRIPT_NAME variable that may arrive in the
# environ when it is called

答案 1 :(得分:1)

如果您已经使用遍历,为什么不使用它来返回您的" rest API root"金字塔遍历/rest/时的对象?从那里,一切都会自然而然地发挥作用。

class ApplicationRoot(object):

    def __getitem__(self, name):
        if name == "rest":
            return RestAPIRoot(parent=self, name=name)
        ...

如果你的应用树"和" API树"拥有相同的孩子,并且您希望为他们注册不同的视图,具体取决于孩子所在的树的哪个分支,您可以使用containment查看谓词来注册您的API视图,这样他们只会在child位于" API分支":

  

<强>容纳

     

该值应该是对Python类或接口的引用   上下文资源的沿袭中的父对象必须按顺序提供   为此视图找到并调用。资源中的资源   树必须是“位置感知”才能使用此功能。

     

如果未提供包含,则表示接口和类   在决定是否调用时,不考虑血统   查看可赎回。

另一种方法是不构建单独的API树&#34;但要使用你的&#34; main&#34;应用程序&#34; URI空间&#34;作为RESTful API。唯一的问题是GET和可能的POST请求方法已经被采取&#34;在您的资源上并映射到您的&#34; normal&#34;返回HTML或使用HTTP表单POST的视图。有很多方法可以解决这个问题:

  • 使用单独的名称注册API视图,因此,GET /users/123将返回HTML,GET /users/123/json将返回JSON对象。同样,POST /users/123期望发布HTTP表单,POST /users/123/json期望JSON。这种方法的一个好处是你可以在GET /users/123/xml轻松添加一个XML序列化器。

  • 使用自定义视图谓词,因此GET /users/123GET /users/123?format=json会路由到不同的视图。实际上,自金字塔1.2以来,有一个内置的request_param谓词

  • 使用xhr谓词来区分基于HTTP_X_REQUESTED_WITH标头或accept谓词的请求,以区分HTTP_ACCEPT标题