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,并且我们只对任意嵌套的子目录使用遍历。