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

也见