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

24. RESOURCES

physical_path A string representing the “physical path” computed for the resource, as defined by pyramid.traversal.resource_path(resource). It will begin and end with a slash.

virtual_path A string representing the “virtual path” computed for the resource, as defined by Virtual Root Support. This will be identical to the physical path if virtual rooting is not enabled. It will begin and end with a slash.

app_url A string representing the application URL generated during request.resource_url. It will not end with a slash. It represents a potentially customized URL prefix, containing potentially custom scheme, host and port information passed by the user to request.resource_url. It should be preferred over use of request.application_url.

The __resource_url__ method of a resource should return a string representing a URL. If it cannot override the default, it should return None. If it returns None, the default URL will be returned.

Here’s an example __resource_url__ method.

1

2

3

class Resource(object):

def __resource_url__(self, request, info): return info[’app_url’] + info[’virtual_path’]

The above example actually just generates and returns the default URL, which would have been what was generated by the default resource_url machinery, but your code can perform arbitrary logic as necessary. For example, your code may wish to override the hostname or port number of the generated URL.

Note that the URL generated by __resource_url__ should be fully qualified, should end in a slash, and should not contain any query string or anchor elements (only path elements) to work with resource_url().

24.4 Generating the Path To a Resource

pyramid.traversal.resource_path() returns a string object representing the absolute physical path of the resource object based on its position in the resource tree. Each segment of the path is separated with a slash character.

1

2

from pyramid.traversal import resource_path url = resource_path(resource)

266

24.5. FINDING A RESOURCE BY PATH

If resource in the example above was accessible in the tree as root[’a’][’b’], the above example would generate the string /a/b.

Any positional arguments passed in to resource_path() will be appended as path segments to the end of the resource path.

1

2

from pyramid.traversal import resource_path url = resource_path(resource, ’foo’, ’bar’)

If resource in the example above was accessible in the tree as root[’a’][’b’], the above example would generate the string /a/b/foo/bar.

The resource passed in must be location-aware.

The presence or absence of a virtual root has no impact on the behavior of resource_path().

24.5 Finding a Resource by Path

If you have a string path to a resource, you can grab the resource from that place in the application’s resource tree using pyramid.traversal.find_resource().

You can resolve an absolute path by passing a string prefixed with a / as the path argument:

1

2

from pyramid.traversal import find_resource url = find_resource(anyresource, ’/path’)

Or you can resolve a path relative to the resource you pass in by passing a string that isn’t prefixed by /:

1

2

from pyramid.traversal import find_resource url = find_resource(anyresource, ’path’)

Often the paths you pass to find_resource() are generated by the resource_path() API. These APIs are “mirrors” of each other.

If the path cannot be resolved when calling find_resource() (if the respective resource in the tree does not exist), a KeyError will be raised.

See the pyramid.traversal.find_resource() documentation for more information about resolving a path to a resource.

267

24. RESOURCES

24.6 Obtaining the Lineage of a Resource

pyramid.location.lineage() returns a generator representing the lineage of the location aware resource object.

The lineage() function returns the resource it is passed, then each parent of the resource, in order. For example, if the resource tree is composed like so:

1

class Thing(object): pass

2

 

 

3

thing1

= Thing()

4

thing2

= Thing()

5

thing2.__parent__ = thing1

 

 

 

Calling lineage(thing2) will return a generator. When we turn it into a list, we will get:

1

2

list(lineage(thing2))

[ <Thing object at thing2>, <Thing object at thing1> ]

The generator returned by lineage() first returns the resource it was passed unconditionally. Then, if the resource supplied a __parent__ attribute, it returns the resource represented by resource.__parent__. If that resource has a __parent__ attribute, return that resource’s parent, and so on, until the resource being inspected either has no __parent__ attribute or has a __parent__ attribute of None.

See the documentation for pyramid.location.lineage() for more information.

24.7Determining if a Resource is In The Lineage of Another Resource

Use the pyramid.location.inside() function to determine if one resource is in the lineage of another resource.

For example, if the resource tree is:

1

2

3

4

5

class Thing(object): pass

a = Thing()

b = Thing() b.__parent__ = a

268

24.8. FINDING THE ROOT RESOURCE

Calling inside(b, a) will return True, because b has a lineage that includes a. However, calling inside(a, b) will return False because a does not have a lineage that includes b.

The argument list for inside() is (resource1, resource2). resource1 is ‘inside’ resource2 if resource2 is a lineage ancestor of resource1. It is a lineage ancestor if its parent (or one of its parent’s parents, etc.) is an ancestor.

See pyramid.location.inside() for more information.

24.8 Finding the Root Resource

Use the pyramid.traversal.find_root() API to find the root resource. The root resource is the root resource of the resource tree. The API accepts a single argument: resource. This is a resource that is location aware. It can be any resource in the tree for which you want to find the root.

For example, if the resource tree is:

1 class Thing(object): pass

2

3 a = Thing()

4 b = Thing()

5 b.__parent__ = a

Calling find_root(b) will return a.

The root resource is also available as request.root within view callable code.

The presence or absence of a virtual root has no impact on the behavior of find_root(). The root object returned is always the physical root object.

24.9 Resources Which Implement Interfaces

Resources can optionally be made to implement an interface. An interface is used to tag a resource object with a “type” that can later be referred to within view configuration and by pyramid.traversal.find_interface().

Specifying an interface instead of a class as the context or containment predicate arguments within view configuration statements makes it possible to use a single view callable for more than one class of resource object. If your application is simple enough that you see no reason to want to do this, you can skip reading this section of the chapter.

For example, here’s some code which describes a blog entry which also declares that the blog entry implements an interface.

269

24. RESOURCES

1 import datetime

2 from zope.interface import implementer

3 from zope.interface import Interface

4

5 class IBlogEntry(Interface):

6pass

7

8 @implementer(IBlogEntry)

9 class BlogEntry(object):

10def __init__(self, title, body, author):

11self.title = title

12self.body = body

13self.author = author

14self.created = datetime.datetime.now()

This resource consists of two things: the class which defines the resource constructor as the class BlogEntry, and an interface attached to the class via an implementer class decorator using the IBlogEntry interface as its sole argument.

The interface object used must be an instance of a class that inherits from zope.interface.Interface.

A resource class may implement zero or more interfaces. You specify that a resource implements an interface by using the zope.interface.implementer() function as a class decorator. The above BlogEntry resource implements the IBlogEntry interface.

You can also specify that a particular resource instance provides an interface, as opposed to its class. When you declare that a class implements an interface, all instances of that class will also provide that interface. However, you can also just say that a single object provides the interface. To do so, use the zope.interface.directlyProvides() function:

1

import datetime

2

from zope.interface import directlyProvides

3

from zope.interface import Interface

4

 

5

class IBlogEntry(Interface):

6

pass

7

 

8

class BlogEntry(object):

9

def __init__(self, title, body, author):

10self.title = title

11self.body = body

12self.author = author

13self.created = datetime.datetime.now()

270

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