Comparing and Combining Traversal and URL Dispatch¶
(改编自Bayle Shank在https://github.com/bshanks/pyramid/commit/c73b4662c9671b5f2c3be26cf088ee983952ab61a上的贡献)。
下面是一个比较URL调度和遍历的示例。
Let's say we want to map
/hello/login to a function login in the file myapp/views.py
/hello/foo to a function foo in the file myapp/views.py
/hello/listDirectory to a function listHelloDirectory in the file
myapp/views.py
/hello/subdir/listDirectory to a function listSubDirectory in the
file myapp/views.py
使用URL调度,我们可能有:
1config.add_route('helloLogin', '/hello/login')
2config.add_route('helloFoo', '/hello/foo')
3config.add_route('helloList', '/hello/listDirectory')
4config.add_route('list', '/hello/{subdir}/listDirectory')
5
6config.add_view('myapp.views.login', route_name='helloLogin')
7config.add_view('myapp.views.foo', route_name='helloFoo')
8config.add_view('myapp.views.listHelloDirectory', route_name='helloList')
9config.add_view('myapp.views.listSubDirectory', route_name='list')
myapp/views.py request.matchdict['subdir']
With traversal, we have a more complex setup:
1class MyResource(dict):
2 def __init__(self, name, parent):
3 self.__name__ = name
4 self.__parent__ = parent
5
6class MySubdirResource(MyResource):
7 def __init__(self, name, parent):
8 self.__name__ = name
9 self.__parent__ = parent
10
11 # returns a MyResource object when the key is the name
12 # of a subdirectory
13 def __getitem__(self, key):
14 return MySubdirResource(key, self)
15
16class MyHelloResource(MySubdirResource):
17 pass
18
19def myRootFactory(request):
20 rootResource = MyResource('', None)
21 helloResource = MyHelloResource('hello', rootResource)
22 rootResource['hello'] = helloResource
23 return rootResource
24
25config.add_view('myapp.views.login', name='login')
26config.add_view('myapp.views.foo', name='foo')
27config.add_view('myapp.views.listHelloDirectory', context=MyHelloResource,
28 name='listDirectory')
29config.add_view('myapp.views.listSubDirectory', name='listDirectory')
In the traversal example, when a request for /hello/@@login myRootFactory(request) , and gets back the root resource. It calls the MyResource instance's __getitem__('hello') MyHelloResource . We don't traverse the next path segment ( ``@@login`), because the `` @ `` means the text that follows it is an explicit view name, and traversal ends. The view name 'login' is mapped to the `` 登录 `` function in ``
/hello/@@foo comes in, a similar thing happens.
When a request for /hello/@@listDirectory comes in, the framework calls myRootFactory(request) , and gets back the root resource. It calls MyRootResource's __getitem__('hello') , and gets back a MyHelloResource 实例。它 does not call MyHelloResource's __getitem__('listDirectory') (由于 @@ 领先 listDirectory myapp.views.listRootDirectory , because the context (the last resource traversed) is an instance of MyHelloResource .
When a request for /hello/xyz/@@listDirectory comes in, the framework calls myRootFactory(request) MyRootResource . It calls MyRootResource's __getitem__('hello') , and gets back a MyHelloResource __getitem__('xyz') MySubdirResource 实例。它 does not 呼叫 __getitem__('listDirectory') 上 MySubdirResource myapp.views.listSubDirectory MyHelloResource MySubdirResource 通过 request.context .
/hello/xyz/abc/listDirectory
如果您愿意,可以将URL调度和遍历(按此顺序)结合起来。因此,我们可以将上面的内容改写为:
1class MyResource(dict):
2 def __init__(self, name, parent):
3 self.__name__ = name
4 self.__parent__ = parent
5
6 # returns a MyResource object unconditionally
7 def __getitem__(self, key):
8 return MyResource(key, self)
9
10def myRootFactory(request):
11 return MyResource('', None)
12
13config = Configurator()
14
15config.add_route('helloLogin', '/hello/login')
16config.add_route('helloFoo', '/hello/foo')
17config.add_route('helloList', '/hello/listDirectory')
18config.add_route('list', '/hello/*traverse', factory=myRootFactory)
19
20config.add_view('myapp.views.login', route_name='helloLogin')
21config.add_view('myapp.views.foo', route_name='helloFoo')
22config.add_view('myapp.views.listHelloDirectory', route_name='helloList')
23config.add_view('myapp.views.listSubDirectory', route_name='list',
24 name='listDirectory')
http://localhost:8080/hello/foo/bar/@@listDirectory
这更简单易读,因为我们使用URL调度来处理树顶部的硬编码URL,并且我们只对任意嵌套的子目录使用遍历。