summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Miller <rob@mochimedia.com>2011-01-12 23:48:37 -0800
committerRob Miller <rob@mochimedia.com>2011-01-12 23:48:37 -0800
commit6fd291025098dfeba2872459a0a9ff64f9de3dce (patch)
treee15cca615380aba42e2240d75c6c738ade53a196
parentec99888c9c15f1ee17157d252ef64ed161042129 (diff)
downloadpyramid-6fd291025098dfeba2872459a0a9ff64f9de3dce.tar.gz
pyramid-6fd291025098dfeba2872459a0a9ff64f9de3dce.tar.bz2
pyramid-6fd291025098dfeba2872459a0a9ff64f9de3dce.zip
Minor edits, typo fixes, term consistency changes.
-rw-r--r--docs/narr/muchadoabouttraversal.rst79
1 files changed, 39 insertions, 40 deletions
diff --git a/docs/narr/muchadoabouttraversal.rst b/docs/narr/muchadoabouttraversal.rst
index bc1b48462..375f6e927 100644
--- a/docs/narr/muchadoabouttraversal.rst
+++ b/docs/narr/muchadoabouttraversal.rst
@@ -43,12 +43,12 @@ ever used a run-of-the-mill file system with folders and files.
URL Dispatch
------------
-Let's step back and consider the problem we're trying to solve, which is
-simple. An HTTP request for a particular path has been routed to our web
-application. The requested path will possibly invoke a specific :term:`view
-callable` function defined somewhere in our app. We're trying to determine
-*which* callable function, if any, should be invoked for a given requested
-URL.
+Let's step back and consider the problem we're trying to solve. An
+HTTP request for a particular path has been routed to our web
+application. The requested path will possibly invoke a specific
+:term:`view callable` function defined somewhere in our app. We're
+trying to determine *which* callable function, if any, should be
+invoked for a given requested URL.
Many systems, including Pyramid, offer a simple solution. They offer the
concept of "URL matching". URL matching approaches this problem by parsing
@@ -59,10 +59,9 @@ request path matches a specific pattern, the associated function is called.
If the request path matches more than one pattern, some conflict resolution
scheme is used, usually a simple order precedence so that the first match
will take priority over any subsequent matches. If a request path doesn't
-match any of the defined patterns, :app:`Pyramid` a "404 Not Found" response
-is returned.
+match any of the defined patterns, a "404 Not Found" response is returned.
-In Pyramid, we offer an implementation of URL mapping which we call
+In Pyramid, we offer an implementation of URL matching which we call
:term:`URL dispatch`. Using :app:`Pyramid` syntax, we might have a match
pattern such as ``/{userid}/photos/{photoid}``, mapped to a ``photo_view()``
function defined somewhere in our code. Then a request for a path such as
@@ -115,7 +114,7 @@ then you understand view lookup.
The major difference between file system lookup and traversal is that a file
system lookup steps through nested directories and files in a file system
-tree, while traversal steps through nested dictionary-type objects in an
+tree, while traversal steps through nested dictionary-type objects in a
:term:`resource tree`. Let's take a detailed look at one of our example
paths, so we can see what I mean:
@@ -123,7 +122,7 @@ The path ``/joeschmoe/photos/photo1``, has four segments: ``/``,
``joeschmoe``, ``photos`` and ``photo1``. With file system lookup we might
have a root folder (``/``) containing a nested folder (``joeschmoe``), which
contains another nested folder (``photos``), which finally contains a JPG
-file ("photo1"). With traversal, we instead have a dictionary-like root
+file (``photo1``). With traversal, we instead have a dictionary-like root
object. Asking for the ``joeschmoe`` key gives us another dictionary-like
object. Asking this in turn for the ``photos`` key gives us yet another
mapping object, which finally (hopefully) contains the resource that we're
@@ -154,9 +153,9 @@ Since :app:`Pyramid` is not a highly opinionated framework, it makes no
restriction on how a :term:`resource` is implemented; a developer can
implement them as he wishes. One common pattern used is to persist all of
the resources, including the root, in a database as a graph. The root object
-is a dictionarylike object. Dictionarylike objects in Python supply a
+is a dictionary-like object. Dictionary-like objects in Python supply a
``__getitem__`` method which is called when key lookup is done. Under the
-hood, when ``adict`` is a dictionarylike object, Python translates
+hood, when ``adict`` is a dictionary-like object, Python translates
``adict['a']`` to ``adict.__getitem__('a')``. Try doing this in a Python
interpreter prompt if you don't believe us:
@@ -174,7 +173,7 @@ interpreter prompt if you don't believe us:
1
-The dictionarylike root object stores the ids of all of its subresources as
+The dictionary-like root object stores the ids of all of its subresources as
keys, and provides a ``__getitem__`` implementation that fetches them. So
``get_root()`` fetches the unique root object, while
``get_root()['joeschmoe']`` returns a different object, also stored in the
@@ -185,12 +184,13 @@ days, or anywhere else, it doesn't matter. As long as the returned objects
provide the dictionary-like API (i.e. as long as they have an appropriately
implemented ``__getitem__`` method) then traversal will work.
-In fact, you don't need a "database" at all. You could trivially implement a
-set of objects with ``__getitem__`` methods that search for files in specific
-directories, and thus precisely recreate the older mechanism of having the
-URL path mapped directly to a folder structure on the file system. Or you
-could use plain dictionaries too. Traversal is in fact a superset of file
-system lookup.
+In fact, you don't need a "database" at all. You could use plain
+dictionaries, with your site's URL structure hard-coded directly in
+the Python source. Or you could trivially implement a set of objects
+with ``__getitem__`` methods that search for files in specific
+directories, and thus precisely recreate the traditional mechanism of
+having the URL path mapped directly to a folder structure on the file
+system. Traversal is in fact a superset of file system lookup.
.. note:: See the chapter entitled :ref:`resources_chapter` for a more
technical overview of resources.
@@ -207,13 +207,14 @@ that you might want to take after finding a :term:`resource`. With our photo
example, for instance, you might want to view the photo in a page, but you
might also want to provide a way for the user to edit the photo and any
associated metadata. We'll call the former the ``view`` view, and the latter
-will be the ``edit`` view (Original, I know.) :app:`Pyramid` has a
-centralized view registry where named views can be associated with specific
-resource types. So in our example, we'll assume that we've registered
-``view`` and ``edit`` views for photo objects, and that we've specified the
-``view`` view as the default, so that ``/joeschmoe/photos/photo1/view`` and
-``/joeschmoe/photos/photo1`` are equivalent. The edit view would sensibly be
-provided by a request for ``/joeschmoe/photos/photo1/edit``.
+will be the ``edit`` view. (Original, I know.) :app:`Pyramid` has a
+centralized view :term:`registry` where named views can be associated with
+specific resource types. So in our example, we'll assume that we've
+registered ``view`` and ``edit`` views for photo objects, and that we've
+specified the ``view`` view as the default, so that
+``/joeschmoe/photos/photo1/view`` and ``/joeschmoe/photos/photo1`` are
+equivalent. The edit view would sensibly be provided by a request for
+``/joeschmoe/photos/photo1/edit``.
Hopefully it's clear that the first portion of the edit view's URL path is
going to resolve to the same resource as the non-edit version, specifically
@@ -232,15 +233,15 @@ response.
You might conceptualize a request for ``/joeschmoe/photos/photo1/edit`` as
ultimately converted into the following piece of Pythonic pseudocode::
-
+
context = get_root()['joeschmoe']['photos']['photo1']
view_callable = get_view(context, 'edit')
request.context = context
view_callable(request)
The ``get_root`` and ``get_view`` functions don't really exist. Internally,
-:app:`Pyramid` does something more complicated. But the example above is a
-reasonable approximation of the view lookup algorithm in pseudocode.
+:app:`Pyramid` does something more complicated. But the example above
+is a reasonable approximation of the view lookup algorithm in pseudocode.
Use Cases
---------
@@ -264,20 +265,18 @@ folder. He might decide to nest folders dozens of layers deep. How will you
construct matching patterns that could account for every possible combination
of paths that might develop?
-It's possible, but it will make for some somewhat ugly URLs. And the
-matching patterns are going to become complex quickly as you try to handle
-all of the edge cases.
+It might be possible, but it certainly won't be easy. The matching
+patterns are going to become complex quickly as you try to handle all
+of the edge cases.
-With traversal, however, it's straightforward. If you want 20 layers of
-nesting, it's no problem. :app:`Pyramid` will happily call ``__getitem__``
+With traversal, however, it's straightforward. 20 layers of nesting would be
+ no problem. :app:`Pyramid` will happily call ``__getitem__``
as many times as it needs to, until it runs out of path segments or until a
resource raises a :exc:`KeyError`. Each resource only needs to know how to
fetch its immediate children, the traversal algorithm takes care of the rest.
-
-One of the key advantages of traversal is that the structure of the resource
-tree can live in the database, and not in the code. It's simple to let users
-modify the tree at runtime to set up their own personalized directory
-structures.
+Also, since the structure of the resource tree can live in the database and
+not in the code, it's simple to let users modify the tree at runtime to set
+up their own personalized "directory" structures.
Another use case in which traversal shines is when there is a need to support
a context-dependent security policy. One example might be a document