summaryrefslogtreecommitdiff
path: root/docs/narr/contextfinding.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/narr/contextfinding.rst')
-rw-r--r--docs/narr/contextfinding.rst141
1 files changed, 141 insertions, 0 deletions
diff --git a/docs/narr/contextfinding.rst b/docs/narr/contextfinding.rst
new file mode 100644
index 000000000..491113e62
--- /dev/null
+++ b/docs/narr/contextfinding.rst
@@ -0,0 +1,141 @@
+.. index::
+ pair: finding; context
+
+.. _contextfinding_chapter:
+
+Context Finding
+---------------
+
+In order for a web application to perform any useful action, the web
+framework must provide a mechanism to find and invoke code written by
+the application developer based on parameters present in the
+:term:`request`.
+
+:mod:`repoze.bfg` uses two separate but cooperating subsystems to find
+and invoke code written by the application developer: :term:`context
+finding` and :term:`view lookup`.
+
+- A :mod:`repoze.bfg` :term:`context finding` subsystem is given a
+ :term:`request`; it is responsible for finding a :term:`context`
+ object and a :term:`view name` based on information present in the
+ request.
+
+- Using the context and view name provided by :term:`context finding`,
+ the :mod:`repoze.bfg` view lookup subsystem is provided with a
+ :term:`request`, a :term:`context` and a :term:`view name`. It is
+ then responsible for finding and invoking a :term:`view callable`.
+ A view callable is a specific bit of code that receives the
+ :term:`request` and which returns a :term:`response`, written and
+ registered by the application developer.
+
+These two subsystems are are used by :mod:`repoze.bfg` serially:
+first, a :term:`context finding` 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 Context Finding Subsystem?
+
+ The :term:`URL dispatch` mode of :mod:`repoze.bfg` as well as many
+ other web frameworks such as :term:`Pylons` or :term:`Django`
+ actually collapse the two steps of context finding 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 context and find
+ a view. However, explicitly finding a context 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 context.
+
+This chapter documents :term:`context finding`. There are two
+separate :term:`context finding` subsystems in :mod:`repoze.bfg`:
+:term:`traversal` and :term:`URL dispatch`. The subsystems are
+documented within this chapter. They can be used separately or they
+can be combined.
+
+There is only one :term:`view lookup` subsystem present in
+:mod:`repoze.bfg`. Where appropriate, within this chapter, we
+describe how view lookup interacts with context finding.
+
+.. toctree::
+ :maxdepth: 2
+
+ traversal
+ urldispatch
+ hybrid
+
+Should I Use Traversal or URL Dispatch for Context Finding?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:term:`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 member in the system.
+You just match everything "below" ``members`` to a particular
+:term:`view callable`. For example, you might configure URL dispatch
+within :mod:`repoze.bfg` to match against the following URL patterns:
+
+.. code-block:: text
+
+ members/:membername
+ archives/:year/:month/:day
+
+In this configuration, there will be exactly two types of URLs that
+will be meaningful to your application: URLs that start with
+``/members`` which are followed by a path segment containing a
+member's name. And URLs that start with ``/archives`` and have
+subsequent path elements that represent a year, month, and day. Each
+route pattern will be mapped to a specific :term:`view callable`.
+
+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, and all the URL matching elements are listed
+in a single place.
+
+URL dispatch is not very good, however, at inferring the difference
+between sets of URLs such as these:
+
+.. code-block:: text
+
+ http://example.com/members/Chris/document
+ http://example.com/members/Chris/stuff/page
+
+If you'd like the ``document`` in the first URL above to represent a
+PDF document, and ``/stuff/page`` in the second to represent an
+OpenOffice document in a "stuff" folder, it's hard to express this
+using URL dispatch. It takes more pattern matching assertions to be
+able to make hierarchies like these 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.
+
+However, the other URL mapping mode supported by :mod:`repoze.bfg`,
+named :term:`traversal`, *does* work well for URLs that represent
+arbitrary-depth hierarchies. When traversal is used, each URL segment
+represents a single traversal step through an edge of a graph, so a
+URL like ``http://example.com/a/b/c`` can be thought of as a graph
+traversal on the ``example.com`` site through the edges ``a``, ``b``,
+and ``c``. 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 models as a graph that
+can be traversed, it also becomes easy to provide "instance-level
+security": you just attach a security declaration to each instance in
+the graph. 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
+graph and requires that the developer think about mapping URLs to code
+in terms of traversing that graph. However, when you have a
+hierarchical data store, using traversal can provide significant
+advantages over using URL-based dispatch.
+
+Since :mod:`repoze.bfg` provides support for both approaches, you can
+use either as you see fit; you can even combine them together if
+necessary.
+