Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 678 lines (504 sloc) 26.469 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
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
48 - Various helpful :app:`Pyramid` API methods expect a resource as an
70acd25 @mcdonc module name contractions
mcdonc authored
49 argument (e.g. :func:`~pyramid.url.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
86 :linenos:
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
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
91 root = Resource({'a':Resource({'b':Resource({'c':Resource()})})})
92
93 The resource tree we've created above is represented by a dictionary-like
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 children.
96 It is therefore possible to access ``c`` like so:
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
104 path ``/a/b/c`` would find the ``c`` object in the resource tree as the
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
f361e49 clean up ".. warning" and ".. note" broken by docutils 0.8 upgrade
Michael authored
163 .. warning::
164
165 If your root resource has a ``__name__`` argument that is not ``None`` or the
166 empty string, URLs returned by the :func:`~pyramid.url.resource_url` function
167 and paths generated by the :func:`~pyramid.traversal.resource_path` and
168 :func:`~pyramid.traversal.resource_path_tuple` APIs will be generated
169 improperly. The value of ``__name__`` will be prepended to every path and
170 URL generated (as opposed to a single leading slash or empty tuple element).
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
171
172 .. sidebar:: Using :mod:`pyramid_traversalwrapper`
173
174 If you'd rather not manage the ``__name__`` and ``__parent__`` attributes
175 of your resources "by hand", an add-on package named
176 :mod:`pyramid_traversalwrapper` can help.
177
178 In order to use this helper feature, you must first install the
179 :mod:`pyramid_traversalwrapper` package (available via PyPI), then register
180 its ``ModelGraphTraverser`` as the traversal policy, rather than the
181 default :app:`Pyramid` traverser. The package contains instructions for
182 doing so.
183
184 Once :app:`Pyramid` is configured with this feature, you will no longer
185 need to manage the ``__parent__`` and ``__name__`` attributes on resource
186 objects "by hand". Instead, as necessary, during traversal :app:`Pyramid`
187 will wrap each resource (even the root resource) in a ``LocationProxy``
188 which will dynamically assign a ``__name__`` and a ``__parent__`` to the
5d23bd0 @tomlikestorock fixing typo
tomlikestorock authored
189 traversed resource (based on the last traversed resource and the name
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
190 supplied to ``__getitem__``). The root resource will have a ``__name__``
191 attribute of ``None`` and a ``__parent__`` attribute of ``None``.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
192
163e110 @mcdonc rearrange and add example resource tree
mcdonc authored
193 Applications which use tree-walking :app:`Pyramid` APIs require
194 location-aware resources. These APIs include (but are not limited to)
195 :func:`~pyramid.url.resource_url`, :func:`~pyramid.traversal.find_resource`,
196 :func:`~pyramid.traversal.find_root`,
197 :func:`~pyramid.traversal.find_interface`,
198 :func:`~pyramid.traversal.resource_path`,
199 :func:`~pyramid.traversal.resource_path_tuple`, or
200 :func:`~pyramid.traversal.traverse`, :func:`~pyramid.traversal.virtual_root`,
201 and (usually) :func:`~pyramid.security.has_permission` and
202 :func:`~pyramid.security.principals_allowed_by_permission`.
203
204 In general, since so much :app:`Pyramid` infrastructure depends on
205 location-aware resources, it's a good idea to make each resource in your tree
bac5b32 @mcdonc Features
mcdonc authored
206 location-aware.
207
208 .. index::
209 single: resource_url
210 pair: generating; resource url
211
a9ff226 @mcdonc fix references
mcdonc authored
212 .. _generating_the_url_of_a_resource:
213
bac5b32 @mcdonc Features
mcdonc authored
214 Generating The URL Of A Resource
215 --------------------------------
216
217 If your resources are :term:`location` aware, you can use the
218 :func:`pyramid.url.resource_url` API to generate a URL for the resource.
219 This URL will use the resource's position in the parent tree to create a
220 resource path, and it will prefix the path with the current application URL
221 to form a fully-qualified URL with the scheme, host, port, and path. You can
222 also pass extra arguments to :func:`~pyramid.url.resource_url` to influence
223 the generated URL.
224
225 The simplest call to :func:`~pyramid.url.resource_url` looks like this:
226
227 .. code-block:: python
228 :linenos:
229
230 from pyramid.url import resource_url
231 url = resource_url(resource, request)
232
233 The ``request`` passed to ``resource_url`` in the above example is an
a42a1ef @kyle-johnson minor grammar fixes ('a' vs 'an')
kyle-johnson authored
234 instance of a :app:`Pyramid` :term:`request` object.
bac5b32 @mcdonc Features
mcdonc authored
235
236 If the resource referred to as ``resource`` in the above example was the root
237 resource, and the host that was used to contact the server was
238 ``example.com``, the URL generated would be ``http://example.com/``.
239 However, if the resource was a child of the root resource named ``a``, the
240 generated URL would be ``http://example.com/a/``.
241
242 A slash is appended to all resource URLs when
243 :func:`~pyramid.url.resource_url` is used to generate them in this simple
244 manner, because resources are "places" in the hierarchy, and URLs are meant
245 to be clicked on to be visited. Relative URLs that you include on HTML pages
c661f30 @caseman remove word typically to improve flow
caseman authored
246 rendered as the result of the default view of a resource are more
bac5b32 @mcdonc Features
mcdonc authored
247 apt to be relative to these resources than relative to their parent.
248
249 You can also pass extra elements to :func:`~pyramid.url.resource_url`:
250
251 .. code-block:: python
252 :linenos:
253
254 from pyramid.url import resource_url
255 url = resource_url(resource, request, 'foo', 'bar')
256
257 If the resource referred to as ``resource`` in the above example was the root
258 resource, and the host that was used to contact the server was
259 ``example.com``, the URL generated would be ``http://example.com/foo/bar``.
260 Any number of extra elements can be passed to
261 :func:`~pyramid.url.resource_url` as extra positional arguments. When extra
262 elements are passed, they are appended to the resource's URL. A slash is not
263 appended to the final segment when elements are passed.
264
265 You can also pass a query string:
266
267 .. code-block:: python
268 :linenos:
269
270 from pyramid.url import resource_url
271 url = resource_url(resource, request, query={'a':'1'})
272
273 If the resource referred to as ``resource`` in the above example was the root
274 resource, and the host that was used to contact the server was
275 ``example.com``, the URL generated would be ``http://example.com/?a=1``.
276
277 When a :term:`virtual root` is active, the URL generated by
278 :func:`~pyramid.url.resource_url` for a resource may be "shorter" than its
279 physical tree path. See :ref:`virtual_root_support` for more information
280 about virtually rooting a resource.
281
282 The shortcut method of the :term:`request` named
283 :meth:`pyramid.request.Request.resource_url` can be used instead of
70acd25 @mcdonc module name contractions
mcdonc authored
284 :func:`~pyramid.url.resource_url` to generate a resource URL.
bac5b32 @mcdonc Features
mcdonc authored
285
286 For more information about generating resource URLs, see the documentation
287 for :func:`pyramid.url.resource_url`.
288
289 .. _overriding_resource_url_generation:
290
291 Overriding Resource URL Generation
292 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
293
294 If a resource object implements a ``__resource_url__`` method, this method
70acd25 @mcdonc module name contractions
mcdonc authored
295 will be called when :func:`~pyramid.url.resource_url` is called to generate a
bac5b32 @mcdonc Features
mcdonc authored
296 URL for the resource, overriding the default URL returned for the resource by
297 :func:`~pyramid.url.resource_url`.
298
299 The ``__resource_url__`` hook is passed two arguments: ``request`` and
300 ``info``. ``request`` is the :term:`request` object passed to
70acd25 @mcdonc module name contractions
mcdonc authored
301 :func:`~pyramid.url.resource_url`. ``info`` is a dictionary with two
bac5b32 @mcdonc Features
mcdonc authored
302 keys:
303
304 ``physical_path``
305 The "physical path" computed for the resource, as defined by
306 ``pyramid.traversal.resource_path(resource)``.
307
308 ``virtual_path``
309 The "virtual path" computed for the resource, as defined by
310 :ref:`virtual_root_support`. This will be identical to the physical path
311 if virtual rooting is not enabled.
312
313 The ``__resource_url__`` method of a resource should return a string
314 representing a URL. If it cannot override the default, it should return
315 ``None``. If it returns ``None``, the default URL will be returned.
316
317 Here's an example ``__resource_url__`` method.
318
319 .. code-block:: python
320 :linenos:
321
322 class Resource(object):
323 def __resource_url__(self, request, info):
324 return request.application_url + info['virtual_path']
325
326 The above example actually just generates and returns the default URL, which
327 would have been what was returned anyway, but your code can perform arbitrary
328 logic as necessary. For example, your code may wish to override the hostname
329 or port number of the generated URL.
330
a827e04 @mcdonc note __resource_url__ requirements
mcdonc authored
331 Note that the URL generated by ``__resource_url__`` should be fully
332 qualified, should end in a slash, and should not contain any query string or
333 anchor elements (only path elements) to work best with
70acd25 @mcdonc module name contractions
mcdonc authored
334 :func:`~pyramid.url.resource_url`.
a827e04 @mcdonc note __resource_url__ requirements
mcdonc authored
335
bac5b32 @mcdonc Features
mcdonc authored
336 Generating the Path To a Resource
337 ---------------------------------
338
339 :func:`pyramid.traversal.resource_path` returns a string object representing
340 the absolute physical path of the resource object based on its position in
341 the resource tree. Each segment of the path is separated with a slash
342 character.
343
344 .. code-block:: python
345 :linenos:
346
347 from pyramid.traversal import resource_path
348 url = resource_path(resource)
349
350 If ``resource`` in the example above was accessible in the tree as
351 ``root['a']['b']``, the above example would generate the string ``/a/b``.
352
70acd25 @mcdonc module name contractions
mcdonc authored
353 Any positional arguments passed in to :func:`~pyramid.traversal.resource_path`
bac5b32 @mcdonc Features
mcdonc authored
354 will be appended as path segments to the end of the resource path.
355
356 .. code-block:: python
357 :linenos:
358
359 from pyramid.traversal import resource_path
360 url = resource_path(resource, 'foo', 'bar')
361
362 If ``resource`` in the example above was accessible in the tree as
363 ``root['a']['b']``, the above example would generate the string
364 ``/a/b/foo/bar``.
365
366 The resource passed in must be :term:`location`-aware.
367
368 The presence or absence of a :term:`virtual root` has no impact on the
369 behavior of :func:`~pyramid.traversal.resource_path`.
370
371 Finding a Resource by Path
372 --------------------------
373
374 If you have a string path to a resource, you can grab the resource from
375 that place in the application's resource tree using
376 :func:`pyramid.traversal.find_resource`.
377
378 You can resolve an absolute path by passing a string prefixed with a ``/`` as
379 the ``path`` argument:
380
381 .. code-block:: python
382 :linenos:
383
384 from pyramid.traversal import find_resource
385 url = find_resource(anyresource, '/path')
386
387 Or you can resolve a path relative to the resource you pass in by passing a
388 string that isn't prefixed by ``/``:
389
390 .. code-block:: python
391 :linenos:
392
393 from pyramid.traversal import find_resource
394 url = find_resource(anyresource, 'path')
395
396 Often the paths you pass to :func:`~pyramid.traversal.find_resource` are
397 generated by the :func:`~pyramid.traversal.resource_path` API. These APIs
398 are "mirrors" of each other.
399
400 If the path cannot be resolved when calling
401 :func:`~pyramid.traversal.find_resource` (if the respective resource in the
402 tree does not exist), a :exc:`KeyError` will be raised.
403
404 See the :func:`pyramid.traversal.find_resource` documentation for more
405 information about resolving a path to a resource.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
406
f4f41f3 @mcdonc - Added "Obtaining the Lineage of a Resource" to the Resources narrative
mcdonc authored
407 Obtaining the Lineage of a Resource
408 -----------------------------------
409
410 :func:`pyramid.location.lineage` returns a generator representing the
4a10119 @caseman add missing space
caseman authored
411 :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
412
413 The :func:`~pyramid.location.lineage` function returns the resource it is
414 passed, then each parent of the resource, in order. For example, if the
415 resource tree is composed like so:
416
417 .. code-block:: python
418 :linenos:
419
420 class Thing(object): pass
421
422 thing1 = Thing()
423 thing2 = Thing()
424 thing2.__parent__ = thing1
425
426 Calling ``lineage(thing2)`` will return a generator. When we turn it into a
427 list, we will get:
428
429 .. code-block:: python
430 :linenos:
f361e49 clean up ".. warning" and ".. note" broken by docutils 0.8 upgrade
Michael authored
431
f4f41f3 @mcdonc - Added "Obtaining the Lineage of a Resource" to the Resources narrative
mcdonc authored
432 list(lineage(thing2))
433 [ <Thing object at thing2>, <Thing object at thing1> ]
434
435 The generator returned by :func:`~pyramid.location.lineage` first returns the
436 resource it was passed unconditionally. Then, if the resource supplied a
437 ``__parent__`` attribute, it returns the resource represented by
438 ``resource.__parent__``. If *that* resource has a ``__parent__`` attribute,
439 return that resource's parent, and so on, until the resource being inspected
440 either has no ``__parent__`` attribute or which has a ``__parent__``
441 attribute of ``None``.
442
443 See the documentation for :func:`pyramid.location.lineage` for more
444 information.
445
446 Determining if a Resource is In The Lineage of Another Resource
447 ---------------------------------------------------------------
448
449 Use the :func:`pyramid.location.inside` function to determine if one resource
450 is in the :term:`lineage` of another resource.
451
452 For example, if the resource tree is:
453
454 .. code-block:: python
455 :linenos:
456
457 class Thing(object): pass
458
459 a = Thing()
460 b = Thing()
461 b.__parent__ = a
462
463 Calling ``inside(b, a)`` will return ``True``, because ``b`` has a lineage
464 that includes ``a``. However, calling ``inside(a, b)`` will return ``False``
465 because ``a`` does not have a lineage that includes ``b``.
466
467 The argument list for :func:`~pyramid.location.inside` is ``(resource1,
468 resource2)``. ``resource1`` is 'inside' ``resource2`` if ``resource2`` is a
469 :term:`lineage` ancestor of ``resource1``. It is a lineage ancestor if its
470 parent (or one of its parent's parents, etc.) is an ancestor.
471
472 See :func:`pyramid.location.inside` for more information.
473
b32bfd3 @mcdonc - Added "Finding the Root Resource" to Resources narrative chapter.
mcdonc authored
474 Finding the Root Resource
475 -------------------------
476
477 Use the :func:`pyramid.traversal.find_root` API to find the :term:`root`
478 resource. The root resource is the root resource of the :term:`resource
479 tree`. The API accepts a single argument: ``resource``. This is a resource
480 that is :term:`location` aware. It can be any resource in the tree for which
481 you want to find the root.
482
483 For example, if the resource tree is:
484
485 .. code-block:: python
486 :linenos:
487
488 class Thing(object): pass
489
490 a = Thing()
491 b = Thing()
492 b.__parent__ = a
493
494 Calling ``find_root(b)`` will return ``a``.
495
496 The root resource is also available as ``request.root`` within :term:`view
497 callable` code.
498
499 The presence or absence of a :term:`virtual root` has no impact on the
500 behavior of :func:`~pyramid.traversal.find_root`. The root object returned
501 is always the *physical* root object.
502
8c56ae4 - Added manual index entries to generated index.
Chris McDonough authored
503 .. index::
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
504 single: resource interfaces
8c56ae4 - Added manual index entries to generated index.
Chris McDonough authored
505
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
506 .. _resources_which_implement_interfaces:
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
507
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
508 Resources Which Implement Interfaces
509 ------------------------------------
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
510
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
511 Resources can optionally be made to implement an :term:`interface`. An
512 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
513 referred to within :term:`view configuration` and by
514 :func:`pyramid.traversal.find_interface`.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
515
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
516 Specifying an interface instead of a class as the ``context`` or
517 ``containment`` predicate arguments within :term:`view configuration`
b32bfd3 @mcdonc - Added "Finding the Root Resource" to Resources narrative chapter.
mcdonc authored
518 statements makes it possible to use a single view callable for more than one
519 class of resource object. If your application is simple enough that you see
520 no reason to want to do this, you can skip reading this section of the
521 chapter.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
522
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
523 For example, here's some code which describes a blog entry which also
524 declares that the blog entry implements an :term:`interface`.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
525
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
526 .. code-block:: python
527 :linenos:
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
528
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
529 import datetime
530 from zope.interface import implements
531 from zope.interface import Interface
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
532
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
533 class IBlogEntry(Interface):
534 pass
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
535
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
536 class BlogEntry(object):
537 implements(IBlogEntry)
538 def __init__(self, title, body, author):
539 self.title = title
5e2c481 @mgedmin Whitespace bigotry.
mgedmin authored
540 self.body = body
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
541 self.author = author
542 self.created = datetime.datetime.now()
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
543
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
544 This resource consists of two things: the class which defines the resource
545 constructor as the class ``BlogEntry``, and an :term:`interface` attached to
546 the class via an ``implements`` statement at class scope using the
547 ``IBlogEntry`` interface as its sole argument.
8c56ae4 - Added manual index entries to generated index.
Chris McDonough authored
548
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
549 The interface object used must be an instance of a class that inherits from
550 :class:`zope.interface.Interface`.
9313f14 Roles.
Chris McDonough authored
551
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
552 A resource class may implement zero or more interfaces. You specify that a
553 resource implements an interface by using the
554 :func:`zope.interface.implements` function at class scope. The above
555 ``BlogEntry`` resource implements the ``IBlogEntry`` interface.
9313f14 Roles.
Chris McDonough authored
556
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
557 You can also specify that a particular resource *instance* provides an
558 interface, as opposed to its class. When you declare that a class implements
559 an interface, all instances of that class will also provide that interface.
560 However, you can also just say that a single object provides the interface.
561 To do so, use the :func:`zope.interface.directlyProvides` function:
9313f14 Roles.
Chris McDonough authored
562
563 .. code-block:: python
564 :linenos:
565
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
566 from zope.interface import directlyProvides
567 from zope.interface import Interface
9313f14 Roles.
Chris McDonough authored
568
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
569 class IBlogEntry(Interface):
570 pass
9313f14 Roles.
Chris McDonough authored
571
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
572 class BlogEntry(object):
573 def __init__(self, title, body, author):
574 self.title = title
5e2c481 @mgedmin Whitespace bigotry.
mgedmin authored
575 self.body = body
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
576 self.author = author
577 self.created = datetime.datetime.now()
9313f14 Roles.
Chris McDonough authored
578
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
579 entry = BlogEntry('title', 'body', 'author')
580 directlyProvides(entry, IBlogEntry)
9313f14 Roles.
Chris McDonough authored
581
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
582 :func:`zope.interface.directlyProvides` will replace any existing interface
583 that was previously provided by an instance. If a resource object already
584 has instance-level interface declarations that you don't want to replace, use
585 the :func:`zope.interface.alsoProvides` function:
9313f14 Roles.
Chris McDonough authored
586
587 .. code-block:: python
588 :linenos:
589
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
590 from zope.interface import alsoProvides
591 from zope.interface import directlyProvides
592 from zope.interface import Interface
9313f14 Roles.
Chris McDonough authored
593
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
594 class IBlogEntry1(Interface):
595 pass
9313f14 Roles.
Chris McDonough authored
596
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
597 class IBlogEntry2(Interface):
598 pass
9313f14 Roles.
Chris McDonough authored
599
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
600 class BlogEntry(object):
601 def __init__(self, title, body, author):
602 self.title = title
5e2c481 @mgedmin Whitespace bigotry.
mgedmin authored
603 self.body = body
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
604 self.author = author
605 self.created = datetime.datetime.now()
9313f14 Roles.
Chris McDonough authored
606
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
607 entry = BlogEntry('title', 'body', 'author')
608 directlyProvides(entry, IBlogEntry1)
609 alsoProvides(entry, IBlogEntry2)
9313f14 Roles.
Chris McDonough authored
610
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
611 :func:`zope.interface.alsoProvides` will augment the set of interfaces
612 directly provided by an instance instead of overwriting them like
613 :func:`zope.interface.directlyProvides` does.
9313f14 Roles.
Chris McDonough authored
614
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
615 For more information about how resource interfaces can be used by view
616 configuration, see :ref:`using_resource_interfaces`.
9313f14 Roles.
Chris McDonough authored
617
b32bfd3 @mcdonc - Added "Finding the Root Resource" to Resources narrative chapter.
mcdonc authored
618 Finding a Resource With a Class or Interface in Lineage
619 -------------------------------------------------------
620
70acd25 @mcdonc module name contractions
mcdonc authored
621 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
622 is of a particular Python class, or which implements some :term:`interface`.
623
624 For example, if your resource tree is composed as follows:
625
626 .. code-block:: python
627 :linenos:
628
629 class Thing1(object): pass
630 class Thing2(object): pass
631
632 a = Thing1()
633 b = Thing2()
634 b.__parent__ = a
635
636 Calling ``find_interface(a, Thing1)`` will return the ``a`` resource because
637 ``a`` is of class ``Thing1`` (the resource passed as the first argument is
638 considered first, and is returned if the class or interface spec matches).
639
640 Calling ``find_interface(b, Thing1)`` will return the ``a`` resource because
641 ``a`` is of class ``Thing1`` and ``a`` is the first resource in ``b``'s
642 lineage of this class.
643
644 Calling ``find_interface(b, Thing2)`` will return the ``b`` resource.
645
646 The second argument to find_interface may also be a :term:`interface` instead
647 of a class. If it is an interface, each resource in the lineage is checked
648 to see if the resource implements the specificed interface (instead of seeing
649 if the resource is of a class). See also
650 :ref:`resources_which_implement_interfaces`.
651
8c56ae4 - Added manual index entries to generated index.
Chris McDonough authored
652 .. index::
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
653 single: resource API functions
654 single: url generation (traversal)
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
655
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
656 :app:`Pyramid` API Functions That Act Against Resources
657 -------------------------------------------------------
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
658
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
659 A resource object is used as the :term:`context` provided to a view. See
660 :ref:`traversal_chapter` and :ref:`urldispatch_chapter` for more information
661 about how a resource object becomes the context.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
662
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
663 The APIs provided by :ref:`traversal_module` are used against resource
664 objects. These functions can be used to find the "path" of a resource, the
665 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
666
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
667 The APIs provided by :ref:`location_module` are used against resources.
668 These can be used to walk down a resource tree, or conveniently locate one
669 resource "inside" another.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
670
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
671 Some APIs in :ref:`security_module` accept a resource object as a parameter.
70acd25 @mcdonc module name contractions
mcdonc authored
672 For example, the :func:`~pyramid.security.has_permission` API accepts a
fb6a5ce @mcdonc model -> resource; resource -> asset
mcdonc authored
673 resource object as one of its arguments; the ACL is obtained from this
674 resource or one of its ancestors. Other APIs in the :mod:`pyramid.security`
675 module also accept :term:`context` as an argument, and a context is always a
676 resource.
e60df41 - Added a "Resources" chapter to the narrative documentation which
Chris McDonough authored
677
Something went wrong with that request. Please try again.