summaryrefslogtreecommitdiff
path: root/docs/narr/resourcelocation.rst
blob: 8ddc890edaa4b3a9a25ac0ed1bc9cb0cea40a3d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
.. index::
   single: resource location

.. _resourcelocation_chapter:

Resource Location and View Lookup
---------------------------------

:app:`Pyramid` uses two separate but cooperating subsystems to find and
invoke :term:`view callable` code written by the application developer:
:term:`resource location` and :term:`view lookup`.

- First, a :app:`Pyramid` :term:`resource location` subsystem is given a
  :term:`request`; it is responsible for finding a :term:`resource` object
  based on information present in the request.  When a resource is found via
  resource location, it becomes known as the :term:`context`.

- Next, using the context resource found by :term:`resource location` and the
  :term:`request`, :term:`view lookup` is then responsible for finding and
  invoking a :term:`view callable`.  A view callable is a specific bit of
  code written and registered by the application developer which receives the
  :term:`request` and which returns a :term:`response`.

These two subsystems are used by :app:`Pyramid` serially: first, a
:term:`resource location` subsystem does its job.  Then the result of
resource location is passed to the :term:`view lookup` subsystem.  The view
lookup system finds a :term:`view callable` written by an application
developer, and invokes it.  A view callable returns a :term:`response`.  The
response is returned to the requesting user.

There are two separate :term:`resource location` subsystems in
:app:`Pyramid`: :term:`traversal` and :term:`URL dispatch`. They can be used
separately or they can be combined.  Three chapters which follow describe
:term:`resource location`: :ref:`traversal_chapter`,
:ref:`urldispatch_chapter` and :ref:`hybrid_chapter`.

There is only one :term:`view lookup` subsystem present in :app:`Pyramid`.
Where appropriate, we will describe how view lookup interacts with context
finding.  One chapter which follows describes :term:`view lookup`:
:ref:`views_chapter`.

Should I Use Traversal or URL Dispatch for Resource Location?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When you use :app:`Pyramid`, you have a choice about how you'd like to
resolve URLs to code: you can use either :term:`traversal` or :term:`URL
dispatch`.  The choice to use traversal vs. URL dispatch is largely
"religious".  Since :app:`Pyramid` provides support for both approaches, you
can use either exclusively or combine them as you see fit.

:term:`URL dispatch` is very straightforward.  When you limit your
application to using URL dispatch, you know every URL that your application
might generate or respond to, all the URL matching elements are listed in a
single place, and you needn't think about :term:`resource location` or
:term:`view lookup` at all.

URL dispatch can easily handle URLs such as
``http://example.com/members/Chris``, where it's assumed that each item
"below" ``members`` in the URL represents a single member in some system.
You just match everything "below" ``members`` to a particular :term:`view
callable`, e.g. ``/members/{memberid}``.

However, URL dispatch is not very convenient if you'd like your URLs to
represent an arbitrary-depth hierarchy.  For example, if you need to infer
the difference between sets of URLs such as these, where the ``document`` in
the first URL represents a PDF document, and ``/stuff/page`` in the second
represents an OpenOffice document in a "stuff" folder.

.. code-block:: text

   http://example.com/members/Chris/document
   http://example.com/members/Chris/stuff/page

It takes more pattern matching assertions to be able to make hierarchies work
in URL-dispatch based systems, and some assertions just aren't possible.
URL-dispatch based systems just don't deal very well with URLs that represent
arbitrary-depth hierarchies.

:term:`URL dispatch` tends to collapse the two steps of :term:`resource
location` and :term:`view lookup` into a single step.  Thus, a URL can map
*directly* to a view callable.  This makes URL dispatch easier to understand
than traversal, because traversal makes you understand how :term:`resource
location` works.  But explicitly locating a resource provides extra
flexibility.  For example, it makes it possible to protect your application
with declarative context-sensitive instance-level :term:`authorization`.

Unlike URL dispatch, :term:`traversal` works well for URLs that represent
arbitrary-depth hierarchies.  Since the path segments that compose a URL are
addressed separately, it becomes very easy to form URLs that represent
arbitrary depth hierarchies in a system that uses traversal.  When you're
willing to treat your application resources as a tree that can be traversed,
it also becomes easy to provide "instance-level security": you just attach an
:term:`ACL` security declaration to each resource in the tree.  This is not
nearly as easy to do when using URL dispatch.

Traversal probably just doesn't make any sense when you possess completely
"square" data stored in a relational database because it requires the
construction and maintenance of a resource tree and requires that the
developer think about mapping URLs to code in terms of traversing that tree.

We'll examine both :term:`URL dispatch` and :term:`traversal` in the next two
chapters.