python route 知識總結
route 可以從url提取相應的引數,如controller,action或者其它使用者自己定義的變數
1.Mapper().connect Mapper().match
- from routes import Mapper
- map = Mapper()
- map.connect(None,"error/{action}/{id}",controller="controller_obj") #定義匹配規則
- result = map.match('error/myapp/4') #匹配url='error/myapp/4'
- #result 匹配結果
-
{'action': u'myapp'
- map.connect(None,"/message/:name",controller='my_contro') #除 {} 外,:也可以作為匹配符號
- result = map.match('/message/12')
- #result 匹配結果
- {'controller': u'my_contro', 'name': u'12'}
2.route.middleware以及Mapper.resource
參照cinder 2013.1版程式碼寫的
- #!/usr/bin/env/python
-
#coding=utf-8
- from routes import Mapper
- from routes import middleware
- import webob.dec
- from wsgiref.simple_server import make_server
- class controller(object):
- def __init__(self):
- self.i = 1
- def __call__(self):
- printself.i
- def search(self):
-
return"do search()"
- def show(self):
- return"do show()"
- def index(self):
- return"do index()"
- def update(self):
- return"do update()"
- def delete(self):
- return"do delete()"
- def create(self):
- return"do create()"
- def create_many(self):
- return"do create_many()"
- def update_many(self):
- return"do update_many()"
- def list_many(self):
- return"do list_many()"
- def delete_many(self):
- return"do delete_many()"
- class appclass(object):
- def __init__(self):
- a = controller()
- map = Mapper()
- """路由匹配條件1"""
- #map.connect('/images',controller=a,
- # action='search',
- # conditions={'method':['GET']})
- """路由匹配條件2"""
- #map.connect('name',"/{action}/{pid}",controller=a)
- """路由匹配條件3"""
- #map.resource("message","messages",controller=a,collection={'search':'GET'})
- """路由匹配條件4"""
- #map.resource('message', 'messages',controller=a,
- #collection={'list_many':'GET','create_many':'POST'},
- #member={'update_many':'POST','delete_many':'POST'})
- """路由匹配條件5"""
- map.resource('message', 'messages',controller=a,path_prefix='/{projectid}',
- collection={'list_many':'GET','create_many':'POST'},
- member={'update_many':'POST','delete_many':'POST'})
- self.route = middleware.RoutesMiddleware(self.dispatch,map)
- @webob.dec.wsgify
- def __call__(self,req):
- returnself.route
- @staticmethod
- @webob.dec.wsgify
- def dispatch(req):
- match = req.environ['wsgiorg.routing_args'][1]
- print"route match result is:",match
- ifnot match:
- return"fake url"
- controller = match['controller']
- action = match['action']
- if hasattr(controller,action):
- func = getattr(controller,action)
- ret = func()
- return ret
- else:
- return"has no action:%s" %action
- if __name__=="__main__":
- app = appclass()
- server = make_server('',8088,app)
- server.serve_forever()
分析:
1)webob.dec.wsgify是webob為WSGI應用程式提供的一個裝飾器,作用是將一個函式轉換成一個WSGI應用。
參考資料 http://tumblr.wachang.net/post/38149417931/python-paste-webob-3
2)routes.middleware.RoutesMiddleware,將接受到的url,自動呼叫map.match()方法,將url進行路由匹配並將結果存入request請求的環境變數['wsgiorg.routing_args'],最後會呼叫其第一個引數給出的函式介面,即self.dispatch。
參考資料 http://blog.csdn.net/networm3/article/details/8666150
3)map.connect 及map.resource均用來建立路由匹配條件
針對程式中的匹配條件1
map.connect('/images',controller=a,action='search',conditions={'method':['GET']})
curl | 路由匹配結果 (程式中的route match result is) | curl請求得到的結果 |
curl -X GET http://localhost:8088/images | {'action': u'search', 'controller': <__main__.controller object at 0x10c2b10>} | "do search()" |
匹配條件指定了curl的動作為GET ,訪問路徑為images 對應的action 為search
匹配條件2
map.connect('name',"/{action}/{pid}",controller=a)
curl | 路由匹配結果 (程式中的route match result is) | curl請求得到的結果 |
curl -X GET http://localhost:8088/show/hihi | {'action': u'show', 'controller': <__main__.controller object at 0x2203b10>, 'pid': u'hihi'} | "do show()" |
curl -X POST http://localhost:8088/failfunc/test | {'action': u'failfunc', 'controller': <__main__.controller object at 0x2203b10>, 'pid': u'test'} | "has no action:failfunc" |
匹配條件3
map.resource("message","messages",controller=a) ,map.resource內部定義了預設的匹配條件
第一個引數message為 member_name(資源名),第二個引數messages為collection_name(資源集合名),一般定義資源集合名為資源名的複數,我這裡隨便取名
collection_name作為訪問的路徑名,且當沒有傳入引數controller時,controller=collection_name
map.resource("message","messages",controller=a) 等同於以下匹配條件:
map.connect('/messages',controller=a,action='index',conditions={'method':['GET']})
map.connect('/messages',controller=a,action='create',conditions={'method':['POST']})
map.connect('/messages/{id}',controller=a,action='show',conditions={'method':['GET']})
map.connect('/messages/{id}',controller=a,action='update',conditions={'method':['PUT']})
map.connect('/messages/{id}',controller=a,action='delete',conditions={'method':['DELETE']})
前兩條是針對整個資源集合的操作,後三條是針對資源集合中某個固定資源的操作
curl | 路由匹配結果 (程式中的route match result is) | curl請求得到的結果 |
curl -X POST http://localhost:8088/messages | {'action': u'create', 'controller': <__main__.controller object at 0x1dbbb10>} | "do create()" |
curl -X GET http://localhost:8088/messages | {'action': u'index', 'controller': <__main__.controller object at 0x1dbbb10>} | "do index()" |
curl -X GET http://localhost:8088/messages/12 | {'action': u'show', 'controller': <__main__.controller object at 0x1dbbb10>, 'id': u'12'} | "do show()" |
curl -X PUT http://localhost:8088/messages/12 | {'action': u'update', 'controller': <__main__.controller object at 0x1dbbb10>, 'id': u'12'} | "do update()" |
curl -X DELETE http://localhost:8088/messages/12 | {'action': u'delete', 'controller': <__main__.controller object at 0x1dbbb10>, 'id': u'12'} | "do delete()" |
當url傳入的id包含'.',會將'.'後的字元竄匹配為format,如輸入的id 為 '12.hihi' ,匹配id='12', format='hihi'
匹配條件4
map.resource('message', 'messages',controller=a,
collection={'search':'GET','create_many':'POST'},
member={'update_many':'POST','delete_many':'POST'})
map.resource除了預設的路由條件外,還可以額外的定義‘資源集合的方法’以及‘單個資源的方法’
collection={'search':'GET','create_many':'POST'} 定義了資源集合方法 search,其curl動作為GET,create_many,其curl動作為POST
member={'update_many':'POST','delete_many':'POST'} 定義了單個資源方法 update_many,其curl動作為POST,delete_many,其curl動作為POST
curl | 路由匹配結果 (程式中的route match result is) | curl請求得到的結果 |
curl -X GET http://localhost:8088/messages/search | {'action': u'search', 'controller': <__main__.controller object at 0x253db10>} | do search() |
curl -X POST http://localhost:8088/messages/create_many | {'action': u'create_many', 'controller': <__main__.controller object at 0x253db10>} | do create_many() |
curl -X POST http://localhost:8088/messages/1/update_many | {'action': u'update_many', 'controller': <__main__.controller object at 0x253db10>, 'id': u'1'} | do update_many() |
curl -X POST http://localhost:8088/messages/1/delete_many | {'action': u'delete_many', 'controller': <__main__.controller object at 0x253db10>, 'id': u'1'} | do delete_many() |
匹配條件5
map.resource('message', 'messages',controller=a,path_prefix='/{projectid}',
collection={'list_many':'GET','create_many':'POST'},
member={'update_many':'POST','delete_many':'POST'})
map.resource初始化時還可以指定curl訪問路徑的字首路徑,如匹配條件3及4沒有指定時,預設為collection_name(資源集合名)
指定path_prefix後,路徑為path_prefix/collection_name
curl | 路由匹配結果 (程式中的route match result is) | curl請求得到的結果 |
curl -X POST http://localhost:8088/proj1/messages | {'action': u'create', 'projectid': u'proj1', 'controller': <__main__.controller object at 0x1375b10>} | do create() |
curl -X GET http://localhost:8088/proj1/messages/list_many | {'action': u'list_many', 'projectid': u'proj1', 'controller': <__main__.controller object at 0x1375b10>} | do list_many() |
curl -X POST http://localhost:8088/proj1/messages/member_3/update_many | {'action': u'update_many', 'projectid': u'proj1', 'controller': <__main__.controller object at 0x1375b10>, 'id': u'member_3'} | do update_many() |
在路由5的條件下,新增一條
map.resource('type', 'types',controller=other_controller,
parent_resource=dict(member_name='message',
collection_name='messages'),
path_prefix = '{projectid}/%s/:%s_id' %('nex','nexs'))
curl -X POST http://localhost:8088/proj1/nex/17/types
匹配nexs_id 為17,controller 為other_controller, parent_resource的作用為形成name_prefix = 'message_',具體作用不詳,有待研究
參考資料:http://routes.readthedocs.org/en/latest/restful.html
疑問:
resource中的controller物件的類定義必須要有__call__,要不然,匹配後變為type(controller)為unicode,原因不明,有待研究