Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 708 lines (526 sloc) 27.263 kB
f7c3672 @mcdonc edit much ado chapter
mcdonc authored
1 .. _resources_chapter:
2
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
3 Resources
4 =========
5
14575f5 @caseman reword, reorder paragraph for clarity
caseman authored
6 A :term:`resource` is an object that represents a "place" in a tree
7 related to your application. Every :app:`Pyramid` application has at
8 least one resource object: the :term:`root` resource. Even if you don't
9 define a root resource manually, a default one is created for you. The
10 root resource is the root of a :term:`resource tree`. A resource tree
11 is a set of nested dictionary-like objects which you can use to
12 represent your website's structure.
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
13
14 In an application which uses :term:`traversal` to map URLs to code, the
14575f5 @caseman reword, reorder paragraph for clarity
caseman authored
15 resource tree structure is used heavily to map each URL to a :term:`view
16 callable`. When :term:`traversal` is used, :app:`Pyramid` will walk
17 through the resource tree by traversing through its nested dictionary
18 structure in order to find a :term:`context` resource. Once a context
19 resource is found, the context resource and data in the request will be
20 used to find a :term:`view callable`.
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
21
22 In an application which uses :term:`URL dispatch`, the resource tree is only
23 used indirectly, and is often "invisible" to the developer. In URL dispatch
24 applications, the resource "tree" is often composed of only the root resource
25 by itself. This root resource sometimes has security declarations attached
26 to it, but is not required to have any. In general, the resource tree is
27 much less important in applications that use URL dispatch than applications
28 that use traversal.
29
30 In "Zope-like" :app:`Pyramid` applications, resource objects also often store
5f0a81a @caseman make it clear that leaf resource's __getitem__ must always raise KeyE…
caseman authored
31 data persistently, and offer methods related to mutating that persistent data.
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
32 In these kinds of applications, resources not only represent the site
a5ffd62 @mcdonc model->resource; make docs render without warnings
mcdonc authored
33 structure of your website, but they become the :term:`domain model` of the
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
34 application.
35
36 Also:
37
38 - The ``context`` and ``containment`` predicate arguments to
70acd25 @mcdonc module name contractions
mcdonc authored
39 :meth:`~pyramid.config.Configurator.add_view` (or a
40 :func:`~pyramid.view.view_config` decorator) reference a resource class
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
41 or resource :term:`interface`.
42
43 - A :term:`root factory` returns a resource.
44
45 - A resource is exposed to :term:`view` code as the :term:`context` of a
46 view.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
47
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
48 - Various helpful :app:`Pyramid` API methods expect a resource as an argument
49 (e.g. :meth:`~pyramid.request.Request.resource_url` and others).
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
50
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
51 .. index::
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
52 single: resource tree
53 single: traversal tree
54 single: object tree
55 single: container resources
56 single: leaf resources
57
58 Defining a Resource Tree
59 ------------------------
60
61 When :term:`traversal` is used (as opposed to a purely :term:`url dispatch`
62 based application), :app:`Pyramid` expects to be able to traverse a tree
63 composed of resources (the :term:`resource tree`). Traversal begins at a
64 root resource, and descends into the tree recursively, trying each resource's
65 ``__getitem__`` method to resolve a path segment to another resource object.
66 :app:`Pyramid` imposes the following policy on resource instances in the
67 tree:
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
68
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
69 - A container resource (a resource which contains other resources) must
70 supply a ``__getitem__`` method which is willing to resolve a unicode name
71 to a sub-resource. If a sub-resource by a particular name does not exist
72 in a container resource, ``__getitem__`` method of the container resource
73 must raise a :exc:`KeyError`. If a sub-resource by that name *does* exist,
74 the container's ``__getitem__`` should return the sub-resource.
75
76 - Leaf resources, which do not contain other resources, must not implement a
5f0a81a @caseman make it clear that leaf resource's __getitem__ must always raise KeyE…
caseman authored
77 ``__getitem__``, or if they do, their ``__getitem__`` method must always
78 raise a :exc:`KeyError`.
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
79
80 See :ref:`traversal_chapter` for more information about how traversal
81 works against resource instances.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
82
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
83 Here's a sample resource tree, represented by a variable named ``root``:
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
84
85 .. code-block:: python
392a6c7 @ztane Removed extra indentation from some examples (:linenos: should be ind…
ztane authored
86 :linenos:
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
87
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
88 class Resource(dict):
89 pass
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
90
5483175 @mcdonc minor edits to cito's edits
mcdonc authored
91 root = Resource({'a':Resource({'b':Resource({'c':Resource()})})})
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
92
93 The resource tree we've created above is represented by a dictionary-like
2e3f70d @Cito Some more small fixes in the narrative docu.
Cito authored
94 root object which has a single child named ``'a'``. ``'a'`` has a single child
95 named ``'b'``, and ``'b'`` has a single child named ``'c'``, which has no
96 children. It is therefore possible to access the ``'c'`` leaf resource like so:
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
97
98 .. code-block:: python
99 :linenos:
100
101 root['a']['b']['c']
102
103 If you returned the above ``root`` object from a :term:`root factory`, the
2e3f70d @Cito Some more small fixes in the narrative docu.
Cito authored
104 path ``/a/b/c`` would find the ``'c'`` object in the resource tree as the
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
105 result of :term:`traversal`.
106
107 In this example, each of the resources in the tree is of the same class.
108 This is not a requirement. Resource elements in the tree can be of any type.
109 We used a single class to represent all resources in the tree for the sake of
110 simplicity, but in a "real" app, the resources in the tree can be arbitrary.
111
112 Although the example tree above can service a traversal, the resource
113 instances in the above example are not aware of :term:`location`, so their
114 utility in a "real" application is limited. To make best use of built-in
115 :app:`Pyramid` API facilities, your resources should be "location-aware".
116 The next section details how to make resources location-aware.
117
118 .. index::
119 pair: location-aware; resource
120
121 .. _location_aware:
122
123 Location-Aware Resources
124 ------------------------
125
126 In order for certain :app:`Pyramid` location, security, URL-generation, and
127 traversal APIs to work properly against the resources in a resource tree, all
128 resources in the tree must be :term:`location` -aware. This means they must
129 have two attributes: ``__parent__`` and ``__name__``.
130
131 The ``__parent__`` attribute of a location-aware resource should be a
132 reference to the resource's parent resource instance in the tree. The
133 ``__name__`` attribute should be the name with which a resource's parent
134 refers to the resource via ``__getitem__``.
135
136 The ``__parent__`` of the root resource should be ``None`` and its
137 ``__name__`` should be the empty string. For instance:
138
139 .. code-block:: python
140 :linenos:
141
142 class MyRootResource(object):
143 __name__ = ''
144 __parent__ = None
145
146 A resource returned from the root resource's ``__getitem__`` method should
147 have a ``__parent__`` attribute that is a reference to the root resource, and
148 its ``__name__`` attribute should match the name by which it is reachable via
149 the root resource's ``__getitem__``. A container resource within the root
150 resource should have a ``__getitem__`` that returns resources with a
151 ``__parent__`` attribute that points at the container, and these subobjects
152 should have a ``__name__`` attribute that matches the name by which they are
153 retrieved from the container via ``__getitem__``. This pattern continues
154 recursively "up" the tree from the root.
155
156 The ``__parent__`` attributes of each resource form a linked list that points
bac5b32 @mcdonc Features
mcdonc authored
157 "downwards" toward the root. This is analogous to the `..` entry in
158 filesystem directories. If you follow the ``__parent__`` values from any
159 resource in the resource tree, you will eventually come to the root resource,
160 just like if you keep executing the ``cd ..`` filesystem command, eventually
161 you will reach the filesystem root directory.
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
162
012b976 @goodwillcoding fixed up all the warning dealing ..note and ..warn
goodwillcoding authored
163 .. warning::
164
165 If your root resource has a ``__name__`` argument that is not
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
166 ``None`` or the empty string, URLs returned by the
167 :func:`~pyramid.request.Request.resource_url` function and paths generated
168 by the :func:`~pyramid.traversal.resource_path` and
169 :func:`~pyramid.traversal.resource_path_tuple` APIs will be generated
170 improperly. The value of ``__name__`` will be prepended to every path and
171 URL generated (as opposed to a single leading slash or empty tuple
172 element).
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
173
e556961 @tshepang replace a sentence that doesn't quite fit
tshepang authored
174 .. sidebar:: For your convenience
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
175
176 If you'd rather not manage the ``__name__`` and ``__parent__`` attributes
177 of your resources "by hand", an add-on package named
178 :mod:`pyramid_traversalwrapper` can help.
179
180 In order to use this helper feature, you must first install the
181 :mod:`pyramid_traversalwrapper` package (available via PyPI), then register
182 its ``ModelGraphTraverser`` as the traversal policy, rather than the
183 default :app:`Pyramid` traverser. The package contains instructions for
184 doing so.
185
186 Once :app:`Pyramid` is configured with this feature, you will no longer
187 need to manage the ``__parent__`` and ``__name__`` attributes on resource
188 objects "by hand". Instead, as necessary, during traversal :app:`Pyramid`
189 will wrap each resource (even the root resource) in a ``LocationProxy``
190 which will dynamically assign a ``__name__`` and a ``__parent__`` to the
5d23bd0 @tomlikestorock fixing typo
tomlikestorock authored
191 traversed resource (based on the last traversed resource and the name
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
192 supplied to ``__getitem__``). The root resource will have a ``__name__``
193 attribute of ``None`` and a ``__parent__`` attribute of ``None``.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
194
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
195 Applications which use tree-walking :app:`Pyramid` APIs require
196 location-aware resources. These APIs include (but are not limited to)
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
197 :meth:`~pyramid.request.Request.resource_url`,
198 :func:`~pyramid.traversal.find_resource`,
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
199 :func:`~pyramid.traversal.find_root`,
200 :func:`~pyramid.traversal.find_interface`,
201 :func:`~pyramid.traversal.resource_path`,
202 :func:`~pyramid.traversal.resource_path_tuple`, or
203 :func:`~pyramid.traversal.traverse`, :func:`~pyramid.traversal.virtual_root`,
3c2f95e @mgrbyte Security APIs on pyramid.request.Request
mgrbyte authored
204 and (usually) :meth:`~pyramid.request.Request.has_permission` and
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
205 :func:`~pyramid.security.principals_allowed_by_permission`.
206
207 In general, since so much :app:`Pyramid` infrastructure depends on
208 location-aware resources, it's a good idea to make each resource in your tree
bac5b32 @mcdonc Features
mcdonc authored
209 location-aware.
210
211 .. index::
212 single: resource_url
213 pair: generating; resource url
214
a9ff226 @mcdonc fix references
mcdonc authored
215 .. _generating_the_url_of_a_resource:
216
bac5b32 @mcdonc Features
mcdonc authored
217 Generating The URL Of A Resource
218 --------------------------------
219
220 If your resources are :term:`location` aware, you can use the
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
221 :meth:`pyramid.request.Request.resource_url` API to generate a URL for the
222 resource. This URL will use the resource's position in the parent tree to
223 create a resource path, and it will prefix the path with the current
224 application URL to form a fully-qualified URL with the scheme, host, port,
225 and path. You can also pass extra arguments to
226 :meth:`~pyramid.request.Request.resource_url` to influence the generated URL.
bac5b32 @mcdonc Features
mcdonc authored
227
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
228 The simplest call to :meth:`~pyramid.request.Request.resource_url` looks like
229 this:
bac5b32 @mcdonc Features
mcdonc authored
230
231 .. code-block:: python
232 :linenos:
233
8fd6ba0 @replaceafill Edited docs/narr/resources.rst via GitHub
replaceafill authored
234 url = request.resource_url(resource)
bac5b32 @mcdonc Features
mcdonc authored
235
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
236 The ``request`` in the above example is an instance of a :app:`Pyramid`
237 :term:`request` object.
bac5b32 @mcdonc Features
mcdonc authored
238
239 If the resource referred to as ``resource`` in the above example was the root
240 resource, and the host that was used to contact the server was
241 ``example.com``, the URL generated would be ``http://example.com/``.
242 However, if the resource was a child of the root resource named ``a``, the
243 generated URL would be ``http://example.com/a/``.
244
245 A slash is appended to all resource URLs when
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
246 :meth:`~pyramid.request.Request.resource_url` is used to generate them in
247 this simple manner, because resources are "places" in the hierarchy, and URLs
248 are meant to be clicked on to be visited. Relative URLs that you include on
249 HTML pages rendered as the result of the default view of a resource are more
bac5b32 @mcdonc Features
mcdonc authored
250 apt to be relative to these resources than relative to their parent.
251
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
252 You can also pass extra elements to
253 :meth:`~pyramid.request.Request.resource_url`:
bac5b32 @mcdonc Features
mcdonc authored
254
255 .. code-block:: python
256 :linenos:
257
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
258 url = request.resource_url(resource, 'foo', 'bar')
bac5b32 @mcdonc Features
mcdonc authored
259
260 If the resource referred to as ``resource`` in the above example was the root
261 resource, and the host that was used to contact the server was
262 ``example.com``, the URL generated would be ``http://example.com/foo/bar``.
263 Any number of extra elements can be passed to
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
264 :meth:`~pyramid.request.Request.resource_url` as extra positional arguments.
265 When extra elements are passed, they are appended to the resource's URL. A
266 slash is not appended to the final segment when elements are passed.
bac5b32 @mcdonc Features
mcdonc authored
267
268 You can also pass a query string:
269
270 .. code-block:: python
271 :linenos:
272
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
273 url = request.resource_url(resource, query={'a':'1'})
bac5b32 @mcdonc Features
mcdonc authored
274
275 If the resource referred to as ``resource`` in the above example was the root
276 resource, and the host that was used to contact the server was
277 ``example.com``, the URL generated would be ``http://example.com/?a=1``.
278
279 When a :term:`virtual root` is active, the URL generated by
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
280 :meth:`~pyramid.request.Request.resource_url` for a resource may be "shorter"
281 than its physical tree path. See :ref:`virtual_root_support` for more
282 information about virtually rooting a resource.
bac5b32 @mcdonc Features
mcdonc authored
283
284 For more information about generating resource URLs, see the documentation
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
285 for :meth:`pyramid.request.Request.resource_url`.
bac5b32 @mcdonc Features
mcdonc authored
286
6ce1e0c @mcdonc add more index markers
mcdonc authored
287 .. index::
288 pair: resource URL generation; overriding
289
bac5b32 @mcdonc Features
mcdonc authored
290 .. _overriding_resource_url_generation:
291
292 Overriding Resource URL Generation
293 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
294
295 If a resource object implements a ``__resource_url__`` method, this method
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
296 will be called when :meth:`~pyramid.request.Request.resource_url` is called
297 to generate a URL for the resource, overriding the default URL returned for
298 the resource by :meth:`~pyramid.request.Request.resource_url`.
bac5b32 @mcdonc Features
mcdonc authored
299
300 The ``__resource_url__`` hook is passed two arguments: ``request`` and
301 ``info``. ``request`` is the :term:`request` object passed to
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
302 :meth:`~pyramid.request.Request.resource_url`. ``info`` is a dictionary with
05b5925 @omh Resources.rst quick typo fix
omh authored
303 the following keys:
bac5b32 @mcdonc Features
mcdonc authored
304
305 ``physical_path``
0a6a26c @mcdonc docs fixes
mcdonc authored
306 A string representing the "physical path" computed for the resource, as
307 defined by ``pyramid.traversal.resource_path(resource)``. It will begin
308 and end with a slash.
bac5b32 @mcdonc Features
mcdonc authored
309
310 ``virtual_path``
0a6a26c @mcdonc docs fixes
mcdonc authored
311 A string representing the "virtual path" computed for the resource, as
312 defined by :ref:`virtual_root_support`. This will be identical to the
313 physical path if virtual rooting is not enabled. It will begin and end
314 with a slash.
315
316 ``app_url``
317 A string representing the application URL generated during
318 ``request.resource_url``. It will not end with a slash. It represents a
319 potentially customized URL prefix, containing potentially custom scheme,
320 host and port information passed by the user to ``request.resource_url``.
321 It should be preferred over use of ``request.application_url``.
bac5b32 @mcdonc Features
mcdonc authored
322
323 The ``__resource_url__`` method of a resource should return a string
324 representing a URL. If it cannot override the default, it should return
325 ``None``. If it returns ``None``, the default URL will be returned.
326
327 Here's an example ``__resource_url__`` method.
328
329 .. code-block:: python
330 :linenos:
331
332 class Resource(object):
333 def __resource_url__(self, request, info):
0a6a26c @mcdonc docs fixes
mcdonc authored
334 return info['app_url'] + info['virtual_path']
bac5b32 @mcdonc Features
mcdonc authored
335
336 The above example actually just generates and returns the default URL, which
0a6a26c @mcdonc docs fixes
mcdonc authored
337 would have been what was generated by the default ``resource_url`` machinery,
338 but your code can perform arbitrary logic as necessary. For example, your
339 code may wish to override the hostname or port number of the generated URL.
bac5b32 @mcdonc Features
mcdonc authored
340
a827e04 @mcdonc note __resource_url__ requirements
mcdonc authored
341 Note that the URL generated by ``__resource_url__`` should be fully
342 qualified, should end in a slash, and should not contain any query string or
0a6a26c @mcdonc docs fixes
mcdonc authored
343 anchor elements (only path elements) to work with
fb90f01 @mcdonc - The ``route_url``, ``route_path``, ``resource_url``, ``static_url``…
mcdonc authored
344 :meth:`~pyramid.request.Request.resource_url`.
a827e04 @mcdonc note __resource_url__ requirements
mcdonc authored
345
6ce1e0c @mcdonc add more index markers
mcdonc authored
346 .. index::
347 single: resource path generation
348
bac5b32 @mcdonc Features
mcdonc authored
349 Generating the Path To a Resource
350 ---------------------------------
351
352 :func:`pyramid.traversal.resource_path` returns a string object representing
353 the absolute physical path of the resource object based on its position in
354 the resource tree. Each segment of the path is separated with a slash
355 character.
356
357 .. code-block:: python
358 :linenos:
359
360 from pyramid.traversal import resource_path
361 url = resource_path(resource)
362
363 If ``resource`` in the example above was accessible in the tree as
364 ``root['a']['b']``, the above example would generate the string ``/a/b``.
365
70acd25 @mcdonc module name contractions
mcdonc authored
366 Any positional arguments passed in to :func:`~pyramid.traversal.resource_path`
bac5b32 @mcdonc Features
mcdonc authored
367 will be appended as path segments to the end of the resource path.
368
369 .. code-block:: python
370 :linenos:
371
372 from pyramid.traversal import resource_path
373 url = resource_path(resource, 'foo', 'bar')
374
375 If ``resource`` in the example above was accessible in the tree as
376 ``root['a']['b']``, the above example would generate the string
377 ``/a/b/foo/bar``.
378
379 The resource passed in must be :term:`location`-aware.
380
381 The presence or absence of a :term:`virtual root` has no impact on the
382 behavior of :func:`~pyramid.traversal.resource_path`.
383
6ce1e0c @mcdonc add more index markers
mcdonc authored
384 .. index::
385 pair: resource; finding by path
386
bac5b32 @mcdonc Features
mcdonc authored
387 Finding a Resource by Path
388 --------------------------
389
390 If you have a string path to a resource, you can grab the resource from
391 that place in the application's resource tree using
392 :func:`pyramid.traversal.find_resource`.
393
394 You can resolve an absolute path by passing a string prefixed with a ``/`` as
395 the ``path`` argument:
396
397 .. code-block:: python
398 :linenos:
399
400 from pyramid.traversal import find_resource
401 url = find_resource(anyresource, '/path')
402
403 Or you can resolve a path relative to the resource you pass in by passing a
404 string that isn't prefixed by ``/``:
405
406 .. code-block:: python
407 :linenos:
408
409 from pyramid.traversal import find_resource
410 url = find_resource(anyresource, 'path')
411
412 Often the paths you pass to :func:`~pyramid.traversal.find_resource` are
413 generated by the :func:`~pyramid.traversal.resource_path` API. These APIs
414 are "mirrors" of each other.
415
416 If the path cannot be resolved when calling
417 :func:`~pyramid.traversal.find_resource` (if the respective resource in the
418 tree does not exist), a :exc:`KeyError` will be raised.
419
420 See the :func:`pyramid.traversal.find_resource` documentation for more
421 information about resolving a path to a resource.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
422
6ce1e0c @mcdonc add more index markers
mcdonc authored
423 .. index::
424 pair: resource; lineage
425
f4f41f3 @mcdonc - Added "Obtaining the Lineage of a Resource" to the Resources narrative
mcdonc authored
426 Obtaining the Lineage of a Resource
427 -----------------------------------
428
429 :func:`pyramid.location.lineage` returns a generator representing the
4a10119 @caseman add missing space
caseman authored
430 :term:`lineage` of the :term:`location` aware :term:`resource` object.
f4f41f3 @mcdonc - Added "Obtaining the Lineage of a Resource" to the Resources narrative
mcdonc authored
431
432 The :func:`~pyramid.location.lineage` function returns the resource it is
433 passed, then each parent of the resource, in order. For example, if the
434 resource tree is composed like so:
435
436 .. code-block:: python
437 :linenos:
438
439 class Thing(object): pass
440
441 thing1 = Thing()
442 thing2 = Thing()
443 thing2.__parent__ = thing1
444
445 Calling ``lineage(thing2)`` will return a generator. When we turn it into a
446 list, we will get:
447
448 .. code-block:: python
449 :linenos:
2e3f70d @Cito Some more small fixes in the narrative docu.
Cito authored
450
f4f41f3 @mcdonc - Added "Obtaining the Lineage of a Resource" to the Resources narrative
mcdonc authored
451 list(lineage(thing2))
452 [ <Thing object at thing2>, <Thing object at thing1> ]
453
454 The generator returned by :func:`~pyramid.location.lineage` first returns the
455 resource it was passed unconditionally. Then, if the resource supplied a
456 ``__parent__`` attribute, it returns the resource represented by
457 ``resource.__parent__``. If *that* resource has a ``__parent__`` attribute,
458 return that resource's parent, and so on, until the resource being inspected
2e3f70d @Cito Some more small fixes in the narrative docu.
Cito authored
459 either has no ``__parent__`` attribute or has a ``__parent__`` attribute of
460 ``None``.
f4f41f3 @mcdonc - Added "Obtaining the Lineage of a Resource" to the Resources narrative
mcdonc authored
461
462 See the documentation for :func:`pyramid.location.lineage` for more
463 information.
464
465 Determining if a Resource is In The Lineage of Another Resource
466 ---------------------------------------------------------------
467
468 Use the :func:`pyramid.location.inside` function to determine if one resource
469 is in the :term:`lineage` of another resource.
470
471 For example, if the resource tree is:
472
473 .. code-block:: python
474 :linenos:
475
476 class Thing(object): pass
477
478 a = Thing()
479 b = Thing()
480 b.__parent__ = a
481
482 Calling ``inside(b, a)`` will return ``True``, because ``b`` has a lineage
483 that includes ``a``. However, calling ``inside(a, b)`` will return ``False``
484 because ``a`` does not have a lineage that includes ``b``.
485
486 The argument list for :func:`~pyramid.location.inside` is ``(resource1,
487 resource2)``. ``resource1`` is 'inside' ``resource2`` if ``resource2`` is a
488 :term:`lineage` ancestor of ``resource1``. It is a lineage ancestor if its
489 parent (or one of its parent's parents, etc.) is an ancestor.
490
491 See :func:`pyramid.location.inside` for more information.
492
6ce1e0c @mcdonc add more index markers
mcdonc authored
493 .. index::
494 pair: resource; finding root
495
b32bfd3 @mcdonc - Added "Finding the Root Resource" to Resources narrative chapter.
mcdonc authored
496 Finding the Root Resource
497 -------------------------
498
499 Use the :func:`pyramid.traversal.find_root` API to find the :term:`root`
500 resource. The root resource is the root resource of the :term:`resource
501 tree`. The API accepts a single argument: ``resource``. This is a resource
502 that is :term:`location` aware. It can be any resource in the tree for which
503 you want to find the root.
504
505 For example, if the resource tree is:
506
507 .. code-block:: python
508 :linenos:
509
510 class Thing(object): pass
511
512 a = Thing()
513 b = Thing()
514 b.__parent__ = a
515
516 Calling ``find_root(b)`` will return ``a``.
517
518 The root resource is also available as ``request.root`` within :term:`view
519 callable` code.
520
521 The presence or absence of a :term:`virtual root` has no impact on the
522 behavior of :func:`~pyramid.traversal.find_root`. The root object returned
523 is always the *physical* root object.
524
8c56ae4 - Added manual index entries to generated index.
Chris McDonough authored
525 .. index::
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
526 single: resource interfaces
8c56ae4 - Added manual index entries to generated index.
Chris McDonough authored
527
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
528 .. _resources_which_implement_interfaces:
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
529
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
530 Resources Which Implement Interfaces
531 ------------------------------------
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
532
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
533 Resources can optionally be made to implement an :term:`interface`. An
534 interface is used to tag a resource object with a "type" that can later be
b32bfd3 @mcdonc - Added "Finding the Root Resource" to Resources narrative chapter.
mcdonc authored
535 referred to within :term:`view configuration` and by
536 :func:`pyramid.traversal.find_interface`.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
537
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
538 Specifying an interface instead of a class as the ``context`` or
539 ``containment`` predicate arguments within :term:`view configuration`
b32bfd3 @mcdonc - Added "Finding the Root Resource" to Resources narrative chapter.
mcdonc authored
540 statements makes it possible to use a single view callable for more than one
541 class of resource object. If your application is simple enough that you see
542 no reason to want to do this, you can skip reading this section of the
543 chapter.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
544
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
545 For example, here's some code which describes a blog entry which also
546 declares that the blog entry implements an :term:`interface`.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
547
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
548 .. code-block:: python
549 :linenos:
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
550
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
551 import datetime
1ca5b34 @mcdonc - Replace all mentions of zope.interface.implements with
mcdonc authored
552 from zope.interface import implementer
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
553 from zope.interface import Interface
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
554
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
555 class IBlogEntry(Interface):
556 pass
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
557
1ca5b34 @mcdonc - Replace all mentions of zope.interface.implements with
mcdonc authored
558 @implementer(IBlogEntry)
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
559 class BlogEntry(object):
560 def __init__(self, title, body, author):
561 self.title = title
5e2c481 @mgedmin Whitespace bigotry.
mgedmin authored
562 self.body = body
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
563 self.author = author
564 self.created = datetime.datetime.now()
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
565
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
566 This resource consists of two things: the class which defines the resource
567 constructor as the class ``BlogEntry``, and an :term:`interface` attached to
1ca5b34 @mcdonc - Replace all mentions of zope.interface.implements with
mcdonc authored
568 the class via an ``implementer`` class decorator using the ``IBlogEntry``
569 interface as its sole argument.
8c56ae4 - Added manual index entries to generated index.
Chris McDonough authored
570
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
571 The interface object used must be an instance of a class that inherits from
572 :class:`zope.interface.Interface`.
9313f14 Roles.
Chris McDonough authored
573
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
574 A resource class may implement zero or more interfaces. You specify that a
575 resource implements an interface by using the
1ca5b34 @mcdonc - Replace all mentions of zope.interface.implements with
mcdonc authored
576 :func:`zope.interface.implementer` function as a class decorator. The above
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
577 ``BlogEntry`` resource implements the ``IBlogEntry`` interface.
9313f14 Roles.
Chris McDonough authored
578
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
579 You can also specify that a particular resource *instance* provides an
580 interface, as opposed to its class. When you declare that a class implements
581 an interface, all instances of that class will also provide that interface.
582 However, you can also just say that a single object provides the interface.
583 To do so, use the :func:`zope.interface.directlyProvides` function:
9313f14 Roles.
Chris McDonough authored
584
585 .. code-block:: python
586 :linenos:
587
2e3f70d @Cito Some more small fixes in the narrative docu.
Cito authored
588 import datetime
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
589 from zope.interface import directlyProvides
590 from zope.interface import Interface
9313f14 Roles.
Chris McDonough authored
591
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
592 class IBlogEntry(Interface):
593 pass
9313f14 Roles.
Chris McDonough authored
594
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
595 class BlogEntry(object):
596 def __init__(self, title, body, author):
597 self.title = title
5e2c481 @mgedmin Whitespace bigotry.
mgedmin authored
598 self.body = body
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
599 self.author = author
600 self.created = datetime.datetime.now()
9313f14 Roles.
Chris McDonough authored
601
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
602 entry = BlogEntry('title', 'body', 'author')
603 directlyProvides(entry, IBlogEntry)
9313f14 Roles.
Chris McDonough authored
604
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
605 :func:`zope.interface.directlyProvides` will replace any existing interface
606 that was previously provided by an instance. If a resource object already
607 has instance-level interface declarations that you don't want to replace, use
608 the :func:`zope.interface.alsoProvides` function:
9313f14 Roles.
Chris McDonough authored
609
610 .. code-block:: python
611 :linenos:
612
2e3f70d @Cito Some more small fixes in the narrative docu.
Cito authored
613 import datetime
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
614 from zope.interface import alsoProvides
615 from zope.interface import directlyProvides
616 from zope.interface import Interface
9313f14 Roles.
Chris McDonough authored
617
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
618 class IBlogEntry1(Interface):
619 pass
9313f14 Roles.
Chris McDonough authored
620
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
621 class IBlogEntry2(Interface):
622 pass
9313f14 Roles.
Chris McDonough authored
623
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
624 class BlogEntry(object):
625 def __init__(self, title, body, author):
626 self.title = title
5e2c481 @mgedmin Whitespace bigotry.
mgedmin authored
627 self.body = body
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
628 self.author = author
629 self.created = datetime.datetime.now()
9313f14 Roles.
Chris McDonough authored
630
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
631 entry = BlogEntry('title', 'body', 'author')
632 directlyProvides(entry, IBlogEntry1)
633 alsoProvides(entry, IBlogEntry2)
9313f14 Roles.
Chris McDonough authored
634
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
635 :func:`zope.interface.alsoProvides` will augment the set of interfaces
636 directly provided by an instance instead of overwriting them like
637 :func:`zope.interface.directlyProvides` does.
9313f14 Roles.
Chris McDonough authored
638
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
639 For more information about how resource interfaces can be used by view
640 configuration, see :ref:`using_resource_interfaces`.
9313f14 Roles.
Chris McDonough authored
641
6ce1e0c @mcdonc add more index markers
mcdonc authored
642 .. index::
643 pair: resource; finding by interface or class
644
b32bfd3 @mcdonc - Added "Finding the Root Resource" to Resources narrative chapter.
mcdonc authored
645 Finding a Resource With a Class or Interface in Lineage
646 -------------------------------------------------------
647
70acd25 @mcdonc module name contractions
mcdonc authored
648 Use the :func:`~pyramid.traversal.find_interface` API to locate a parent that
b32bfd3 @mcdonc - Added "Finding the Root Resource" to Resources narrative chapter.
mcdonc authored
649 is of a particular Python class, or which implements some :term:`interface`.
650
651 For example, if your resource tree is composed as follows:
652
653 .. code-block:: python
654 :linenos:
655
656 class Thing1(object): pass
657 class Thing2(object): pass
658
659 a = Thing1()
660 b = Thing2()
661 b.__parent__ = a
662
663 Calling ``find_interface(a, Thing1)`` will return the ``a`` resource because
664 ``a`` is of class ``Thing1`` (the resource passed as the first argument is
665 considered first, and is returned if the class or interface spec matches).
666
667 Calling ``find_interface(b, Thing1)`` will return the ``a`` resource because
668 ``a`` is of class ``Thing1`` and ``a`` is the first resource in ``b``'s
669 lineage of this class.
670
671 Calling ``find_interface(b, Thing2)`` will return the ``b`` resource.
672
673 The second argument to find_interface may also be a :term:`interface` instead
674 of a class. If it is an interface, each resource in the lineage is checked
675 to see if the resource implements the specificed interface (instead of seeing
2033eeb @stevepiercy - Garden PR #1121
stevepiercy authored
676 if the resource is of a class).
677
678 .. seealso::
679
680 See also :ref:`resources_which_implement_interfaces`.
b32bfd3 @mcdonc - Added "Finding the Root Resource" to Resources narrative chapter.
mcdonc authored
681
8c56ae4 - Added manual index entries to generated index.
Chris McDonough authored
682 .. index::
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
683 single: resource API functions
684 single: url generation (traversal)
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
685
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
686 :app:`Pyramid` API Functions That Act Against Resources
687 -------------------------------------------------------
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
688
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
689 A resource object is used as the :term:`context` provided to a view. See
690 :ref:`traversal_chapter` and :ref:`urldispatch_chapter` for more information
691 about how a resource object becomes the context.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
692
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
693 The APIs provided by :ref:`traversal_module` are used against resource
694 objects. These functions can be used to find the "path" of a resource, the
695 root resource in a resource tree, or to generate a URL for a resource.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
696
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
697 The APIs provided by :ref:`location_module` are used against resources.
698 These can be used to walk down a resource tree, or conveniently locate one
699 resource "inside" another.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
700
3c2f95e @mgrbyte Security APIs on pyramid.request.Request
mgrbyte authored
701 Some APIs on the :class:`pyramid.request.Request` accept a resource object as a parameter.
702 For example, the :meth:`~pyramid.request.Request.has_permission` API accepts a
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
703 resource object as one of its arguments; the ACL is obtained from this
3c2f95e @mgrbyte Security APIs on pyramid.request.Request
mgrbyte authored
704 resource or one of its ancestors. Other security related APIs on the
705 :class:`pyramid.request.Request` class also accept :term:`context` as an argument,
706 and a context is always a resource.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
707
Something went wrong with that request. Please try again.