summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-11-23 16:55:12 +0000
committerChris McDonough <chrism@agendaless.com>2009-11-23 16:55:12 +0000
commit4c4c5aff62a5b8813a41784279c997b71fb46508 (patch)
treee18a717eeb950213fd652aaa526c658dc3ad78d0 /docs
parent5ece24fc5808226ab33ca79c84dc795b5facc09d (diff)
downloadpyramid-4c4c5aff62a5b8813a41784279c997b71fb46508.tar.gz
pyramid-4c4c5aff62a5b8813a41784279c997b71fb46508.tar.bz2
pyramid-4c4c5aff62a5b8813a41784279c997b71fb46508.zip
Holy circdeps batman.
Diffstat (limited to 'docs')
-rw-r--r--docs/glossary.rst7
-rw-r--r--docs/narr/configuration.rst147
2 files changed, 116 insertions, 38 deletions
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 0e8f982a9..b50b77f96 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -92,7 +92,12 @@ Glossary
View name
The "URL name" of a view, e.g ``index.html``. If a view is
configured without a name, its name is considered to be the empty
- string (which implies the "default view").
+ string (which implies the :term:`default view`).
+ Default view
+ The default view of a model is the view invoked when the
+ :term:`view name` is the empty string (``''``). This is the case
+ when :term:`traversal` exhausts the path elements in the PATH_INFO
+ of a request before it returns a :term:`context`.
Virtualenv
An isolated Python environment. Allows you to control which
packages are used on a particular project by cloning your main
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst
index 276cc1f0c..c5cb60405 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -193,6 +193,75 @@ but return a response with the body ``Hello world!``; the
``goodbye_world`` view callable returns a response with the body
``Goodbye world!``.
+Traversal and The Default View
+------------------------------
+
+If you've used the code in this tutorial already, you've actually
+unwittingly configured :mod:`repoze.bfg` to serve an application that
+relies on :term:`traversal`. A full explanation of how
+:mod:`repoze.bfg` locates "the right" :term:`view callable` for a
+given request requires some explanation of traversal.
+
+In :mod:`repoze.bfg` terms, :term:`traversal` is the act of descending
+a *directed graph* of objects using the individual path segments of
+the path info portion of a URL in order to find a :term:`context`
+object. The graph is traversed, beginning at a root object,
+represented by ``/``; if there are further path segments in the path
+info, the root object's ``__getitem__`` is called with the next path
+segment, and it is presumed to return another graph object, *ad
+infinitum* until all path segments are exhausted; if any node in the
+graph doesn't *have* a ``__getitem__`` method, or if the
+``__getitem__`` of a node raises a ``KeyError``, traversal ends
+immediately.
+
+Here's an image that depicts the :mod:`repoze.bfg` traversal process
+graphically as a flowchart:
+
+.. image:: modelgraphtraverser.png
+
+The results of a :term:`traversal` include a :term:`context` and a
+:term:`view name`. The :term:`view name` is the *first* URL path
+segment in the set of path segments "left over" during
+:term:`traversal`. Effectively, if traversal returns a non-empty
+:term:`view name`, it means that traversal ran out of nodes in the
+graph before it finished exhausting all the path segments implied by
+the path info of the URL: no segments are "left over". In this case,
+a non-default view will be invoked.
+
+The :term:`default view` of a :term:`context` is represented by a
+:term:`view configuration` that has the :term:`view name` of the empty
+string. The :term:`default view` is found when all path elements in
+the URL *are* exhausted before :term:`traversal` returns a
+:term:`context` object, causing the :term:`view name` to be ``''``
+(the empty string). When no path segements are "left over" after
+traversal, the :term:`default view` for the context found is invoked.
+
+Our application's :term:`root` object is a default root object used
+when one isn't otherwise specified in application configuration. This
+root object does not have a ``__getitem__`` method, thus it has no
+children. Although in a more complex system there can be many
+contexts which URLs resolve to in our application, effectively there
+is only ever one context: the root object.
+
+We have only a single default view registered (the registration for
+the ``hello_world`` view callable). Due to this set of circumstances,
+you can consider the sole possible URL that will resolve to a default
+view in this application the root URL ``'/'``. It is the only URL
+that will resolve to the :term:`view name` of ``''`` (the empty
+string).
+
+We have only a single view registered for the :term:`view name`
+``goodbye`` (the registration for the ``goodbye_world`` view
+callable). Due to this set of circumstances, you can consider the
+sole possible URL that will resolve to the ``goodbye_world`` in this
+application the URL ``'/goodbye'`` because it is the only URL that
+will resolve to the :term:`view name` of ``goodbye``.
+
+.. note::
+
+ For more in-depth information about :term:`traversal`, see
+ :ref:`traversal_chapter`.
+
.. _helloworld_imperative_appconfig:
Application Configuration
@@ -269,36 +338,21 @@ The line ``config.add_view(hello_world)`` registers the
of a Configurator must be called with a view callable object as its
first argument, so the first argument passed is ``hello_world``
function we'd like to use as a :term:`view callable`. However, this
-line calls ``add_view`` with no additional :term:`predicate`
-arguments, meaning that we'd like :mod:`repoze.bfg` to invoke the
-``hello_world`` view callable for *any* request if another more
-specific view configuration (one with more specific predicate
-arguments) doesn't match it more closely.
+line calls ``add_view`` with a single default :term:`predicate`
+argument, the ``name`` predicate with a value of ``''``, meaning that
+we'd like :mod:`repoze.bfg` to invoke the ``hello_world`` view
+callable for any request for the :term:`default view` of an object.
Since our ``hello_world`` view callable returns a Response instance
with a body of ``Hello world!``` in the configuration implied by this
script, a user agent to a server running this application will receive
-the greeting ``Hello world!`` when any URL is invoked, unless
-:mod:`repoze.bfg` finds a more specific view configuration in its
-application registry for a given request.
-
-The line ``config.add_view(goodbye_world, name='goodbye')`` registers
-the ``hello_world`` function as a view callble. The line calls
-``add_view`` with the view callable as the first required positional
-argument, and a :term:`predicate` keyword argument ``name`` with the
-value ``'goodbye'``. This :term:`view configuration` implies that a
-request with a :term:`view name` of ``goodbye`` should cause the
-``goodbye_world`` view callable to be invoked. For the purposes of
-this discussion, the :term:`view name` can be considered the first
-non-empty path segment in the URL: in particular, this view
-configuration will match when the URL is ``/goodbye``.
+the greeting ``Hello world!`` when any :term:`default view` is
+invoked, unless :mod:`repoze.bfg` finds a more specific view
+configuration in its application registry for a given request.
-.. sidebar:: View Dispatching and Ordering
+.. sidebar:: View Dispatch and Ordering
- If you've been running the code in this tutorial, you've actually
- unknowingly now configured :mod:`repoze.bfg` to serve an
- application that relies on :term:`traversal`. When
- :term:`traversal` is used, :mod:`repoze.bfg` chooses the most
+ When :term:`traversal` is used, :mod:`repoze.bfg` chooses the most
specific view callable based *only* on view :term:`predicate`
applicability. This is unlike :term:`URL dispatch`, another
dispatch mode of :mod:`repoze.bfg` (and other frameworks, like
@@ -312,6 +366,17 @@ configuration will match when the URL is ``/goodbye``.
``hello_world`` second; :mod:`repoze.bfg` will still give us the
most specific callable when a request is dispatched to it.
+The line ``config.add_view(goodbye_world, name='goodbye')`` registers
+the ``hello_world`` function as a view callble. The line calls
+``add_view`` with the view callable as the first required positional
+argument, and a :term:`predicate` keyword argument ``name`` with the
+value ``'goodbye'``. This :term:`view configuration` implies that a
+request with a :term:`view name` of ``goodbye`` should cause the
+``goodbye_world`` view callable to be invoked. For the purposes of
+this discussion, the :term:`view name` can be considered the first
+non-empty path segment in the URL: in particular, this view
+configuration will match when the URL is ``/goodbye``.
+
Since our ``goodbye_world`` view callable returns a Response instance
with a body of ``Goodbye world!`` in the configuration implied by this
script, a visit by a user agent to the URL that contains the path info
@@ -335,18 +400,20 @@ Earlier we explained that the server would return ``Hello world!`` if
you visited the *root* (``/``) URL. However, actually, because the
view configuration registration for the ``hello_world`` view callable
has no :term:`predicate` arguments, the ``hello_world`` view callable
-is applicable for *any request*. For example, if you visit the URL
-with the path info ``/buz``, you will see ``Hello world!``. The only
-time you *won't* see ``Hello world!`` is when you visit a URL with the
-path info that ends in ``/goodbye``. This is because we've also
-registered a *more specific* view configuration for this circumstance:
+is applicable for the :term:`default view` of any :term:`context`
+resulting from a request. This isn't all that interesting in this
+application, because we only *have* one potential context (the root
+object).
+
+We've also registered a view configuration for another circumstance:
the ``goodbye_world`` view callable has a ``name`` predicate of
-``goodbye``, meaning that it is a better match for requests that have
-the :term:`view name` ``goodbye`` than the more general
-``hello_world`` view configuration registration. Because
-:mod:`repoze.bfg` uses the most specific view configuration for any
-request, the ``goodbye_world`` view callable will be used when the URL
-contains path information that ends with ``/goodbye``.
+``goodbye``, meaning that it will match for requests that have the
+:term:`view name` ``goodbye`` unlike the ``hello_world`` view
+configuration registration, which will only match the default view
+(view name ``''``) of a request. Because :mod:`repoze.bfg` chooses
+the best view configuration for any request, the ``goodbye_world``
+view callable will be used when the URL contains path information that
+ends with ``/goodbye``.
WGSI Application Creation
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -358,7 +425,7 @@ WGSI Application Creation
After configuring views, the script creates a WSGI *application* via
the ``config.make_wsgi_app`` method. A call to ``make_wsgi_app``
-implies that all "configuration" is finished (meaning all method calls
+implies that all configuration is finished (meaning all method calls
to the configurator which set up views, and various other
configuration settings have been performed). The ``make_wsgi_app``
method returns a :term:`WSGI` application object that can be used by
@@ -444,6 +511,9 @@ In a file named ``helloworld.py``:
def hello_world(request):
return Response('Hello world!')
+ def goodbye_world(request):
+ return Response('Goodbye world!')
+
if __name__ == '__main__':
config = Configurator(zcml_file='configure.zcml')
app = config.make_wsgi_app()
@@ -640,7 +710,7 @@ behalf of the developer. Various attributes can be specified on the
creates.
Since the relative ordering of calls to ``Configuration.add_view``
-doesn't matter (see the sidebar above entitled *View Dispatching and
+doesn't matter (see the sidebar above entitled *View Dispatch and
Ordering*), the relative order of ``<view>`` tags in ZCML doesn't
matter either. The following ZCML orderings are completely
equivalent:
@@ -769,6 +839,9 @@ For more information about the API of the ``Configurator`` object, see
:ref:`configuration_module`. The equivalent ZCML declaration tags are
introduced in narrative documentation chapters as necessary.
+For more information about :term:`traversal`, see
+:ref:`traversal_chapter`.
+
For more information about :term:`view configuration`, see
:ref:`views_chapter`.