2012-07-22 44 views
2

好的,我有我的應用程序,它需要根用戶的請求/幾乎所有的東西都在使用遍歷。使用Traversal製作子應用程序的最佳方式

但我想在該網站的頂部做一個休息api。

所以我有兩種選擇。我要麼分開在兩個不同的應用程序,並把其餘的應用程序:rest.site.com,或者我可以將其移動到site.com/rest/*traversal

如果我在做「/休息/ *遍歷」,我假設我將不得不添加一條名爲rest_traversal的路線,其中遍歷路徑將爲*traversal,路線爲/rest/*traversal。我曾經爲管理頁面做過一次。

我想知道是否有最乾淨的方法來做到這一點。我試圖使用virtual_root,但據我所知virtual_root實際上是被添加到遍歷的路徑。

就像virtual_root = /cms並要求/fun將創建下列路徑/cms/fun

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

回答

1

如果你使用遍歷已經,爲什麼不直接用它來當Pyramid遍歷到/rest/時,返回「rest API根」對象?從那裏,一切都會自然而然地發揮作

class ApplicationRoot(object): 

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

如果你的「應用程序樹」和「API樹」具有相同的孩子,你想對他們有依賴於該樹中的子位於的分支,可以使用containment查看註冊的不同看法謂詞來註冊你的API的看法,所以當孩子的「API分支」內,他們將只匹配:

遏制

這個值應該是一個Python類或接口,一個參考 上下文資源的血統中的父對象必須按順序提供 以查找和調用此視圖。您的資源 樹中的資源必須具有「位置感知」才能使用此功能。

如果未提供包容,則在決定是否調用可調用的視圖時,不會考慮系統中的接口和類。

另一種方法不是構建一個單獨的「API樹」,而是使用您的「主」應用程序的「URI空間」作爲RESTful API。唯一的問題是,GET和可能的POST請求方法已經在您的資源上「取得」,並映射到返回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被路由到不同的視圖。其實,還有一個內置的request_param謂詞,由於金字塔1.2

  • 使用xhr謂詞基於HTTP_X_REQUESTED_WITH頁眉或accept謂詞來區分請求發送到HTTP_ACCEPT頭區分

+0

這是一個好主意,沒有考慮重新樹立我的樹。雖然這是答案的一半。遍歷將自然地工作,但會像以前一樣匹配相同的視圖。 – 2012-07-23 21:19:34

+0

@LoïcFaure-Lacroix:我已經擴大了答案 – Sergey 2012-07-23 22:16:55

+0

nitpick:'match_param'用於匹配路線中的模式。 'request_param'是你想要匹配'request.params'字典的一部分(查詢字符串+後主體)。 – 2012-07-24 14:52:51

2

我知道這已回答了,但萬一有人來到這裏尋找另一種可能的方式,使「subapps」,並在金字塔使用它們,我想指出的是,一些有趣的事情可以用pyramid.wsgi

完成
""" 
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 
相關問題