1. 程式人生 > >python route 知識總結

python route 知識總結

route 可以從url提取相應的引數,如controller,action或者其它使用者自己定義的變數

1.Mapper().connect    Mapper().match

  1. from routes import Mapper  
  2. map = Mapper()  
  3. map.connect(None,"error/{action}/{id}",controller="controller_obj"#定義匹配規則
  4. result = map.match('error/myapp/4')  #匹配url='error/myapp/4'
  5. #result 匹配結果
  6. {'action': u'myapp'
    'controller': u'controller_obj''id': u'4'}  
  7. map.connect(None,"/message/:name",controller='my_contro')  #除 {} 外,:也可以作為匹配符號
  8. result = map.match('/message/12')  
  9. #result 匹配結果
  10. {'controller': u'my_contro''name': u'12'}  


2.route.middleware以及Mapper.resource

參照cinder 2013.1版程式碼寫的

  1. #!/usr/bin/env/python
  2. #coding=utf-8
  3. from routes import Mapper  
  4. from routes import middleware  
  5. import webob.dec  
  6. from wsgiref.simple_server import make_server  
  7. class controller(object):  
  8.     def __init__(self):  
  9.         self.i = 1
  10.     def __call__(self):  
  11.         printself.i  
  12.     def search(self):  
  13.         return"do search()"
  14.     def show(self):  
  15.         return"do show()"
  16.     def index(self):  
  17.         return"do index()"
  18.     def update(self):  
  19.         return"do update()"
  20.     def delete(self):  
  21.         return"do delete()"
  22.     def create(self):  
  23.         return"do create()"
  24.     def create_many(self):  
  25.         return"do create_many()"
  26.     def update_many(self):  
  27.         return"do update_many()"
  28.     def list_many(self):  
  29.         return"do list_many()"
  30.     def delete_many(self):  
  31.         return"do delete_many()"
  32. class appclass(object):  
  33.     def __init__(self):  
  34.         a = controller()  
  35.         map = Mapper()  
  36.         """路由匹配條件1"""
  37.         #map.connect('/images',controller=a,
  38.         #           action='search',
  39.         #           conditions={'method':['GET']})
  40.         """路由匹配條件2"""
  41.         #map.connect('name',"/{action}/{pid}",controller=a)
  42.         """路由匹配條件3"""
  43.         #map.resource("message","messages",controller=a,collection={'search':'GET'})
  44.         """路由匹配條件4"""
  45.         #map.resource('message', 'messages',controller=a,
  46.                         #collection={'list_many':'GET','create_many':'POST'},
  47.                         #member={'update_many':'POST','delete_many':'POST'})
  48.         """路由匹配條件5"""
  49.         map.resource('message''messages',controller=a,path_prefix='/{projectid}',  
  50.                     collection={'list_many':'GET','create_many':'POST'},  
  51.                     member={'update_many':'POST','delete_many':'POST'})  
  52.         self.route = middleware.RoutesMiddleware(self.dispatch,map)  
  53.     @webob.dec.wsgify  
  54.     def __call__(self,req):  
  55.         returnself.route  
  56.     @staticmethod
  57.     @webob.dec.wsgify  
  58.     def dispatch(req):  
  59.         match = req.environ['wsgiorg.routing_args'][1]  
  60.         print"route match result is:",match  
  61.         ifnot match:  
  62.             return"fake url"
  63.         controller = match['controller']  
  64.         action = match['action']  
  65.         if hasattr(controller,action):  
  66.             func = getattr(controller,action)  
  67.             ret = func()  
  68.             return ret  
  69.         else:  
  70.             return"has no action:%s" %action  
  71. if __name__=="__main__":  
  72.     app = appclass()  
  73.     server = make_server('',8088,app)  
  74.     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"
匹配條件沒有指定curl的動作,因此所有的動作(PUT,POST,GET,。。)都匹配,第二個curl請求,匹配的action 為failfunc,pid為test,但是程式沒有定義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()"
這裡匹配結果中的id為某個具體資源id,這裡亂取,後三條curl針對具體資源(id為12)的操作,前兩條是針對整個資源集合的操作

當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,原因不明,有待研究