您的位置:首页 > 其它

Routes 起步

2013-07-18 08:32 260 查看
本文地址:/article/1545502.html



[python] view
plaincopyprint?

from routes import Mapper

map = Mapper()

map.connect('spch', '/blog', controller='main', action='index')

result = map.match('/blog')

print result

{'action': u'index', 'controller': u'main'}

1.2 行创建一个mapper

3. 行注册一条路由, 路由名称为'spch', 路径为'/blog', controller为main,

action为index

可以这样认为,匹配到此条路由的请求交由controller处理,请求预调用的

函数为index

5. 创建好路由条目后,即可以进行匹配,调用match方法,匹配路径'blog'

6. 输出匹配结果

[python] view
plaincopyprint?

map.connect(None, "/error/{action}/{id}", controller="error")

result = map.match('/error/index/2')

print result

{'action': u'index', 'controller': u'error', 'id': u'2'}

1.注册了一条无名路由,并且action从匹配路由中获得

同样,我们可以省掉None

map.connect("/error/{action}/{id}", controller="error")

上述语句同样注册了一条无名路由。

Conditions

Conditions用于限制进行路由匹配,比如method

[python] view
plaincopyprint?

m.connect("/user/list", controller="user", action="list", conditions=dict(method=["GET", "HEAD"]))

只匹配GET,HEAD请求。

Requirements

有时只想匹配数字,或者匹配可选的几个条目

[python] view
plaincopyprint?

map.connect(R"/blog/{id:\d+}")

map.connect(R"/download/{platform:windows|mac}/{filename}")

\d表示匹配1位数字,\d+表示匹配多位

windows|mac 表示只匹配windows或者mac

可以将上述写成

[python] view
plaincopyprint?

map.connect("/blog/{id}", requirements={"id": R"\d+"}

map.connect("/download/{platform}/{filename}",

requirements={"platform": R"windows|mac"})

Format extensions

通过{.format}来指定匹配格式

[python] view
plaincopyprint?

map.connect('/entries/{id}{.format}')

print map.match('/entries/2')

{'id': u'2', 'format': None}

print map.match('/entries/2.mp3')

{'id': u'2', 'format': u'mp3'}

[python] view
plaincopyprint?

map.connect('/entries/{id:\d+}{.format:mp3}')

print map.match('/entries/2.mp3')

{'id': u'2', 'format': u'mp3'}

print map.match('/entries/2')

{'id': u'2', 'format': None}

print map.match('/entries/2.mp4')

None

注意:{id:\d+}, 如果没有\d+, print map.match('/entries/2.mp4')将输出 {'id': u'2.mp4', 'format': None}是可以成功的。

有了\d+后,由于没有匹配format,同时\d+要求只匹配数字,所有2.mp4匹配失败

当路由条目过多时,需要一条一条注册,过于麻烦,此时可以通过resource route简化

[python] view
plaincopyprint?

map.connect("messages", "/messages",

controller="messages", action="create",

conditions=dict(method=["POST"]))

map.connect("messages", "/messages",

controller="messages", action="index",

conditions=dict(method=["GET"]))

map.connect("formatted_messages", "/messages.{format}",

controller="messages", action="index",

conditions=dict(method=["GET"]))

map.connect("new_message", "/messages/new",

controller="messages", action="new",

conditions=dict(method=["GET"]))

map.connect("formatted_new_message", "/messages/new.{format}",

controller="messages", action="new",

conditions=dict(method=["GET"]))

map.connect("/messages/{id}",

controller="messages", action="update",

conditions=dict(method=["PUT"]))

map.connect("/messages/{id}",

controller="messages", action="delete",

conditions=dict(method=["DELETE"]))

map.connect("edit_message", "/messages/{id}/edit",

controller="messages", action="edit",

conditions=dict(method=["GET"]))

map.connect("formatted_edit_message", "/messages/{id}.{format}/edit",

controller="messages", action="edit",

conditions=dict(method=["GET"]))

map.connect("message", "/messages/{id}",

controller="messages", action="show",

conditions=dict(method=["GET"]))

map.connect("formatted_message", "/messages/{id}.{format}",

controller="messages", action="show",

conditions=dict(method=["GET"]))

上述路由条目可以使用这一条语句代替。

[python] view
plaincopyprint?

map.resource("message", "messages")

两个参数,一个指定单数,为member路由名字;一个指定复数,为collection路由名字。

函数原型:resource(member_name, collection_name, **kwargs)

[plain] view
plaincopyprint?

GET /messages => messages.index() => url("messages")

POST /messages => messages.create() => url("messages")

GET /messages/new => messages.new() => url("new_message")

PUT /messages/1 => messages.update(id) => url("message", id=1)

DELETE /messages/1 => messages.delete(id) => url("message", id=1)

GET /messages/1 => messages.show(id) => url("message", id=1)

GET /messages/1/edit => messages.edit(id) => url("edit_message", id=1)

这里有必要说一下member 路由与 collection路由。

上述的路由模型

[plain] view
plaincopyprint?

GET /messages => messages.index()

POST /messages => messages.create()

GET /messages/new => messages.new()

PUT /messages/1 => messages.update(id)

DELETE /messages/1 => messages.delete(id)

GET /messages/1 => messages.show(id)

GET /messages/1/edit => messages.edit(id)

1. 有的路由有id, 指向一个具体的对象

2. 有的路由没有id, 指向全体对象

3. 有的路由(index/create, show/update/delete)有相同的URL,但是HTTP method不同

4. 有的路由(show/edit)HTTP method和前缀相同,仅后缀不同

一个member路由指定具体实例,也就是说它们有id。而一个collection路由,

没有指定的实例,即没有给定id

综上:member路由操作一个单独的实例,而collection操作全体实例。

另一个函数collection也可以完成上述功能。

函数原型:collection(collection_name, resource_name, path_prefix=None, member_prefix='/{id}', controller=None, collection_actions=['index', 'create', 'new'],member_actions=['show', 'update',
'delete', 'edit'], member_options=None, **kwargs)

用法:
map.collection('entries', 'entry')


RoutesMiddleware将请求应声到相应WSGI程序,它将路由匹配结果存到environ环境变量中去。

[python] view
plaincopyprint?

from routes.middleware import RoutesMiddleware

app = RoutesMiddleware(wsgi_app, map) # ``map`` is a routes.Mapper.

map调用match匹配URL,并设置WSGI环境变量

[python] view
plaincopyprint?

environ['wsgiorg.routing_args'] = ((url, match))

environ['routes.route'] = route

environ['routes.url'] = url

route为匹配到的路由,url为一个URLGenerator对象,match为匹配所得条目。

app为一个RoutesMiddleware对象,内部重载__call__(def __call__(self, environ, start_response))仍为一个wsgi应用。

wsgi_app为一个wsgi程序,RoutesMiddleware将环境变量(environ)设置好后,调用wsgi_app进行后续处理。

下面是一个实际的输出:

[plain] view
plaincopyprint?

wsgiorg.routing_args = (<routes.util.URLGenerator object at 0x0287AFB0>,

{'action': u'index', 'controller': <__main__.Resourse instance at 0x02876E40>})

routes.route = <routes.route.Route object at 0x02871F10>

routes.url = <routes.util.URLGenerator object at 0x0287AFB0>

本文地址:/article/1545499.html

1.下载库文件

webob库:http://download.csdn.net/detail/spch2008/5497755

routes库:http://download.csdn.net/detail/spch2008/5497757

repoze库:http://download.csdn.net/detail/spch2008/5499231

2. 组织代码



3. 代码

[python] view
plaincopyprint?

'''''

Created on 2013-6-1

@author: spch2008

'''

from wsgiref.simple_server import make_server

import routes.middleware

import webob.dec

import webob.exc

class Controller:

@webob.dec.wsgify

def __call__(self, req):

return webob.Response("Hello World!")

class Router(object):

def __init__(self):

self._mapper = routes.Mapper()

self._mapper.connect('/spch',

controller=Controller(),

action='index',

conditions={'method': ['GET']})

self._router = routes.middleware.RoutesMiddleware(self._dispatch, self._mapper)

@webob.dec.wsgify

def __call__(self, req):

return self._router

@staticmethod

@webob.dec.wsgify

def _dispatch(req):

match = req.environ['wsgiorg.routing_args'][1]

if not match:

return webob.exc.HTTPNotFound()

app = match['controller']

return app

app = Router()

httpd = make_server('localhost', 8282, app)

httpd.serve_forever()

22行:创建一个mapper

23行:#注册一个路由

28行:创建一个RoutesMiddleware对象,匹配路由,修改环境变量后,调用self._dispatch

4. 运行结果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: