Chris McDonough
2010-12-19 36cbf3a071fb76c14dde7f4c4e74cd8464e9919f
rearrange traversal and urldispatch chapters
4 files modified
178 ■■■■■ changed files
docs/index.rst 2 ●●● patch | view | raw | blame | history
docs/latexindex.rst 2 ●●● patch | view | raw | blame | history
docs/narr/resourcelocation.rst 88 ●●●● patch | view | raw | blame | history
docs/narr/urldispatch.rst 86 ●●●●● patch | view | raw | blame | history
docs/index.rst
@@ -39,8 +39,8 @@
   narr/project
   narr/startup
   narr/resourcelocation
   narr/traversal
   narr/urldispatch
   narr/traversal
   narr/hybrid
   narr/views
   narr/handlers
docs/latexindex.rst
@@ -32,8 +32,8 @@
   narr/firstapp
   narr/project
   narr/resourcelocation
   narr/traversal
   narr/urldispatch
   narr/traversal
   narr/hybrid
   narr/views
   narr/handlers
docs/narr/resourcelocation.rst
@@ -6,45 +6,27 @@
Resource Location and View Lookup
---------------------------------
As a primary job, :app:`Pyramid` provides a mechanism to find and invoke code
written by the application developer based on parameters present in the
:term:`request`.
:app:`Pyramid` uses two separate but cooperating subsystems to find and
invoke code written by the application developer: :term:`resource location`
and :term:`view lookup`.
invoke :term:`view callable` code written by the application developer:
:term:`resource location` and :term:`view lookup`.
- A :app:`Pyramid` :term:`resource location` subsystem is given a
- 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`.
- Using the context provided by :term:`resource location`, the :app:`Pyramid`
  :term:`view lookup` subsystem is provided with a :term:`request` and
  :term:`context`.  It 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
- 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 context
finding 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.
.. sidebar::  What Good is A Resource Location Subsystem?
   The :term:`URL dispatch` mode of :app:`Pyramid` as well as many other web
   frameworks such as :term:`Pylons` or :term:`Django` actually collapse the
   two steps of resource location and view lookup into a single step.  In
   these systems, a URL can map *directly* to a view callable.  This makes
   them simpler to understand than systems which use distinct subsystems to
   locate a resource and find a view.  However, explicitly finding a resource
   provides extra flexibility.  For example, it makes it possible to protect
   your application with declarative context-sensitive instance-level
   :term:`authorization`, which is not well-supported in frameworks that do
   not provide a notion of a resource.
: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
@@ -60,8 +42,11 @@
Should I Use Traversal or URL Dispatch for Resource Location?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Since :app:`Pyramid` provides support for both approaches, you can use either
exclusively or combine them as you see fit.
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
@@ -76,9 +61,9 @@
callable`, e.g. ``/members/{memberid}``.
However, URL dispatch is not very convenient if you'd like your URLs to
represent an arbitrary 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
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
@@ -88,22 +73,31 @@
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.
Essentially, URL-dispatch based systems just don't deal very well with URLs
that represent arbitrary-depth hierarchies.
URL-dispatch based systems just don't deal very well with URLs that represent
arbitrary-depth hierarchies.
But :term:`traversal` *does* work well for URLs that represent
: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 eaiser 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 a
security declaration to each resource in the tree.  This is not nearly as
easy to do when using URL dispatch.
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.
In essence, the choice to use traversal vs. URL dispatch is largely
religious.  Traversal dispatch 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 tree and requires that the
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.
However, when you have a hierarchical data store, using traversal can provide
significant advantages over using URL-based dispatch.
We'll examine both :term:`URL dispatch` and :term:`traversal` in the next two
chapters.
docs/narr/urldispatch.rst
@@ -6,41 +6,16 @@
URL Dispatch
============
The URL dispatch feature of :app:`Pyramid` allows you to either augment or
replace :term:`traversal` as a :term:`resource location` mechanism, allowing
URL pattern matching to have the "first crack" at resolving a given URL to
:term:`context` resource.
Although it is a "resource-location" mechanism, ironically, using URL
dispatch exclusively allows you to avoid thinking about your application in
terms of resources entirely.
Many applications don't need :app:`Pyramid` features -- such as
context-sensitive declarative security via an :term:`authorization policy` --
that benefit from having any visible separation between :term:`resource
location` and :term:`view lookup`.  To this end, URL dispatch provides a
handy syntax that allows you to effectively map URLs *directly* to
:term:`view` code in such a way that you needn't think about your application
in terms of "resource location" at all.  This makes developing a
:app:`Pyramid` application seem more like developing an application in a
system that is "resource-free", such as :term:`Pylons` or :term:`Django`.
Whether or not you care about "resources", it often makes a lot of sense to
use :term:`URL dispatch` instead of :term:`traversal` in an application that
has no natural data hierarchy.  For instance, if all the data in your
application lives in a relational database, and that relational database has
no self-referencing tables that form a natural hierarchy, URL dispatch is
easier to use than traversal, and is often a more natural fit for creating an
application that manipulates "flat" data.
:term:`URL dispatch` provides a simple way to map URLs :term:`view` code
using a simple pattern matching language.  An ordered set of patterns is
checked one-by-one.  If one of the patterns matches the path information
associated with a request, a particular :term:`view callable` is invoked.  If
no route matches, :app:`Pyramid` falls back to trying to use
:term:`traversal` to map the current request to a :term:`view callable`.
The presence of calls to the :meth:`pyramid.config.Configurator.add_route`
method within your application is a sign that you're using :term:`URL
dispatch`.
.. note::
  Route configuration may also be added to the system via :term:`ZCML` (see
  :ref:`zcml_route_configuration`).
High-Level Operational Overview
-------------------------------
@@ -50,27 +25,31 @@
matching patterns present in a *route map*.
If any route pattern matches the information in the :term:`request` provided
to :app:`Pyramid`, a route-specific :term:`context` resource will be
generated.  When this happens, :app:`Pyramid` will shortcut
:term:`traversal`, and will invoke :term:`view lookup` using the context
resource and view name generated by URL dispatch.  If the matched route names
a :term:`view callable` in its configuration, that view callable will be
invoked when view lookup is performed.
to :app:`Pyramid`, app:`Pyramid` will shortcut :term:`traversal`, and will
invoke :term:`view lookup` using a :term:`context` resource generated by the
route match.
However, if no route pattern matches the information in the :term:`request`
provided to :app:`Pyramid`, it will fail over to using :term:`traversal` to
perform resource location and view lookup.
Technically, URL dispatch is a :term:`resource location` mechanism (it finds
a context object).  But ironically, using URL dispatch (instead of
:term:`traversal`) allows you to avoid thinking about your application in
terms of "resources" entirely, because it allows you to directly map a
:term:`view callable` to a route.
Route Configuration
-------------------
:term:`Route configuration` is the act of adding a new :term:`route` to an
application.  A route has a *pattern*, representing a pattern meant to match
against the ``PATH_INFO`` portion of a URL, and a *name*, which is used by
developers within a :app:`Pyramid` application to uniquely identify a
particular route when generating a URL.  It also optionally has a
``factory``, a set of :term:`route predicate` parameters, and a set of
:term:`view` parameters.
against the ``PATH_INFO`` portion of a URL (the portion following the scheme
and port, e.g. ``/foo/bar`` in the URL ``http://localhost:8080/foo/bar``),
and a *route name*, which is used by developers within a :app:`Pyramid`
application to uniquely identify a particular route when generating a URL.
It also optionally has a ``factory``, a set of :term:`route predicate`
parameters, and a set of :term:`view` parameters.
.. index::
   single: add_route
@@ -103,10 +82,11 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When a route configuration declaration names a ``view`` attribute, the value
of the attribute will reference a :term:`view callable`.  A view callable, as
described in :ref:`views_chapter`, is developer-supplied code that "does
stuff" as the result of a request.  For more information about how to create
view callables, see :ref:`views_chapter`.
of the attribute will reference a :term:`view callable`.  This view callable
will be invoked when the route matches.  A view callable, as described in
:ref:`views_chapter`, is developer-supplied code that "does stuff" as the
result of a request.  For more information about how to create view
callables, see :ref:`views_chapter`.
Here's an example route configuration that references a view callable:
@@ -136,6 +116,9 @@
callable` named as that ``view`` attribute will always be found and invoked
when the associated route pattern matches during a request.
Route View Callable Registration and Lookup Details
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
The purpose of making it possible to specify a view callable within a route
configuration is to prevent developers from needing to deeply understand the
details of :term:`resource location` and :term:`view lookup`.  When a route
@@ -146,11 +129,8 @@
For most usage, you needn't understand more than this; how it works is an
implementation detail.  In the interest of completeness, however, we'll
explain how it *does* work in the following section.  You can skip it if
you're uninterested.
Route View Callable Registration and Lookup Details
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
explain how it *does* work in the this section.  You can skip it if you're
uninterested.
When a ``view`` attribute is attached to a route configuration,
:app:`Pyramid` ensures that a :term:`view configuration` is registered that
@@ -1257,3 +1237,7 @@
A tutorial showing how :term:`URL dispatch` can be used to create a
:app:`Pyramid` application exists in :ref:`bfg_sql_wiki_tutorial`.
Route configuration may also be added to the system via :term:`ZCML` (see
:ref:`zcml_route_configuration`).