Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
pyramid.pdf
Скачиваний:
11
Добавлен:
24.03.2015
Размер:
3.82 Mб
Скачать

CHAPTER

TWENTYSIX

TRAVERSAL

This chapter explains the technical details of how traversal works in Pyramid.

For a quick example, see hellotraversal.

For more about why you might use traversal, see Much Ado About Traversal.

A traversal uses the URL (Universal Resource Locator) to find a resource located in a resource tree, which is a set of nested dictionary-like objects. Traversal is done by using each segment of the path portion of the URL to navigate through the resource tree. You might think of this as looking up files and directories in a file system. Traversal walks down the path until it finds a published resource, analogous to a file system “directory” or “file”. The resource found as the result of a traversal becomes the context of the request. Then, the view lookup subsystem is used to find some view code willing to “publish” this resource by generating a response.

Using Traversal to map a URL to code is optional. It is often less easy to understand than URL dispatch, so if you’re a rank beginner, it probably makes sense to use URL dispatch to map URLs to code instead of traversal. In that case, you can skip this chapter.

26.1 Traversal Details

Traversal is dependent on information in a request object. Every request object contains URL path information in the PATH_INFO portion of the WSGI environment. The PATH_INFO string is the portion of a request’s URL following the hostname and port number, but before any query string elements or fragment element. For example the PATH_INFO portion of the URL http://example.com:8080/a/b/c?foo=1 is /a/b/c.

281

26. TRAVERSAL

Traversal treats the PATH_INFO segment of a URL as a sequence of path segments. For example, the PATH_INFO string /a/b/c is converted to the sequence [’a’, ’b’, ’c’].

This path sequence is then used to descend through the resource tree, looking up a resource for each path segment. Each lookup uses the __getitem__ method of a resource in the tree.

For example, if the path info sequence is [’a’, ’b’, ’c’]:

Traversal starts by acquiring the root resource of the application by calling the root factory. The root factory can be configured to return whatever object is appropriate as the traversal root of your application.

Next, the first element (’a’) is popped from the path segment sequence and is used as a key to lookup the corresponding resource in the root. This invokes the root resource’s __getitem__ method using that value (’a’) as an argument.

If the root resource “contains” a resource with key ’a’, its __getitem__ method will return it. The context temporarily becomes the “A” resource.

The next segment (’b’) is popped from the path sequence, and the “A” resource’s __getitem__ is called with that value (’b’) as an argument; we’ll presume it succeeds.

The “A” resource’s __getitem__ returns another resource, which we’ll call “B”. The context temporarily becomes the “B” resource.

Traversal continues until the path segment sequence is exhausted or a path element cannot be resolved to a resource. In either case, the context resource is the last object that the traversal successfully resolved. If any resource found during traversal lacks a __getitem__ method, or if its __getitem__ method raises a KeyError, traversal ends immediately, and that resource becomes the context.

The results of a traversal also include a view name. If traversal ends before the path segment sequence is exhausted, the view name is the next remaining path segment element. If the traversal expends all of the path segments, then the view name is the empty string (”).

The combination of the context resource and the view name found via traversal is used later in the same request by the view lookup subsystem to find a view callable. How Pyramid performs view lookup is explained within the View Configuration chapter.

282

26.2. THE RESOURCE TREE

26.2 The Resource Tree

The resource tree is a set of nested dictionary-like resource objects that begins with a root resource. In order to use traversal to resolve URLs to code, your application must supply a resource tree to Pyramid.

In order to supply a root resource for an application the Pyramid Router is configured with a callback known as a root factory. The root factory is supplied by the application, at startup time, as the root_factory argument to the Configurator.

The root factory is a Python callable that accepts a request object, and returns the root object of the resource tree. A function, or class is typically used as an application’s root factory. Here’s an example of a simple root factory class:

1

2

3

class Root(dict):

def __init__(self, request): pass

Here’s an example of using this root factory within startup configuration, by passing it to an instance of a

Configurator named config:

1 config = Configurator(root_factory=Root)

The root_factory argument to the Configurator constructor registers this root factory to be called to generate a root resource whenever a request enters the application. The root factory registered this way is also known as the global root factory. A root factory can alternately be passed to the Configurator as a dotted Python name which can refer to a root factory defined in a different module.

If no root factory is passed to the Pyramid Configurator constructor, or if the root_factory value specified is None, a default root factory is used. The default root factory always returns a resource that has no child resources; it is effectively empty.

Usually a root factory for a traversal-based application will be more complicated than the above Root class; in particular it may be associated with a database connection or another persistence mechanism.

283

26. TRAVERSAL

Emulating the Default Root Factory

For purposes of understanding the default root factory better, we’ll note that you can emulate the default root factory by using this code as an explicit root factory in your application setup:

1

2

3

4

5

class Root(object):

def __init__(self, request): pass

config = Configurator(root_factory=Root)

The default root factory is just a really stupid object that has no behavior or state. Using traversal against an application that uses the resource tree supplied by the default root resource is not very interesting, because the default root resource has no children. Its availability is more useful when you’re developing an application using URL dispatch.

latex-note.png

If the items contained within the resource tree are “persistent” (they have state that lasts longer than the execution of a single process), they become analogous to the concept of domain model objects used by many other frameworks.

The resource tree consists of container resources and leaf resources. There is only one difference between a container resource and a leaf resource: container resources possess a __getitem__ method (making it “dictionary-like”) while leaf resources do not. The __getitem__ method was chosen as the signifying difference between the two types of resources because the presence of this method is how Python itself typically determines whether an object is “containerish” or not (dictionary objects are “containerish”).

Each container resource is presumed to be willing to return a child resource or raise a KeyError based on a name passed to its __getitem__.

Leaf-level instances must not have a __getitem__. If instances that you’d like to be leaves already happen to have a __getitem__ through some historical inequity, you should subclass these resource types and cause their __getitem__ methods to simply raise a KeyError. Or just disuse them and think up another strategy.

Usually, the traversal root is a container resource, and as such it contains other resources. However, it doesn’t need to be a container. Your resource tree can be as shallow or as deep as you require.

284

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]