summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-05-16 18:48:02 +0000
committerChris McDonough <chrism@agendaless.com>2009-05-16 18:48:02 +0000
commit29e01279ff0b13623a6b1b769351632f12bafb35 (patch)
treeb53e44b99df1f4fdf5f3437e7228b53652e53fc0 /docs
parentdfad1fbd9fa46c67aee8de3c3d3b36c0af1ec7bf (diff)
downloadpyramid-29e01279ff0b13623a6b1b769351632f12bafb35.tar.gz
pyramid-29e01279ff0b13623a6b1b769351632f12bafb35.tar.bz2
pyramid-29e01279ff0b13623a6b1b769351632f12bafb35.zip
- The ``RoutesMapper`` class in ``repoze.bfg.urldispatch`` has been
removed, as well as its documentation. It had been deprecated since 0.6.3. Code in ``repoze.bfg.urldispatch.RoutesModelTraverser`` which catered to it has also been removed. - The semantics of the ``route`` ZCML directive have been simplified. Previously, it was assumed that to use a route, you wanted to map a route to an externally registered view. The new ``route`` directive instead has a ``view`` attribute which is required, specifying the dotted path to a view callable. When a route directive is processed, a view is *registered* using the name attribute of the route directive as its name and the callable as its value. The ``view_name`` and ``provides`` attributes of the ``route`` directive are therefore no longer used. Effectively, if you were previously using the ``route`` directive, it means you must change a pair of ZCML directives that look like this:: <route name="home" path="" view_name="login" factory=".models.root.Root" /> <view for=".models.root.Root" name="login" view=".views.login_view" /> To a ZCML directive that looks like this:: <route name="home" path="" view=".views.login_view" factory=".models.root.Root" /> In other words, to make old code work, remove the ``view`` directives that were only there to serve the purpose of backing ``route`` directives, and move their ``view=`` attribute into the ``route`` directive itself. This change also necessitated that the ``name`` attribute of the ``route`` directive is now required. If you were previously using ``route`` directives without a ``name`` attribute, you'll need to add one (the name is arbitrary, but must be unique among all ``route`` and ``view`` statements). The ``provides`` attribute of the ``route`` directive has also been removed. This directive specified a sequence of interface types that the generated context would be decorated with. Since route views are always generated now for a single interface (``repoze.bfg.IRoutesContext``) as opposed to being looked up arbitrarily, there is no need to decorate any context to ensure a view is found. - The Routes ``Route`` object used to resolve the match is now put into the environment as ``bfg.route`` when URL dispatch is used.
Diffstat (limited to 'docs')
-rw-r--r--docs/narr/urldispatch.rst247
1 files changed, 126 insertions, 121 deletions
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 5bb81350c..028c184db 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -9,19 +9,15 @@ also map URLs to code via :term:`URL dispatch` using the
:term:`Routes` framework. The :term:`Routes` framework is a Python
reimplementation of the `Rails routes system
<http://manuals.rubyonrails.com/read/chapter/65>`_. It is a mechanism
-which allows you to declaratively map URLs to code. Both traversal
-and URL dispatch have the same goal: to find the context and the view
-name.
+which allows you to declaratively map URLs to code.
.. note:: In common :term:`Routes` lingo, the code that it maps URLs
to is defined by a *controller* and an *action*. However,
neither concept (controller nor action) exists within
:mod:`repoze.bfg`. Instead, when you map a URL pattern to
- code in bfg, you will map the URL patterm to a
- :term:`context` and a :term:`view name`. Once the context
- and view name are found, the same :term:`view` lookup which
- is detailed in :ref:`traversal_chapter` will be done using
- the context and view name found via a route.
+ code in bfg, you will map the URL patterm to a :term:`view`.
+ Once the context and view name are found, the view will be
+ called with a :term:`context` and a :term:`request`.
It often makes a lot of sense to use :term:`URL dispatch` instead of
:term:`traversal` in an application that has no natural hierarchy.
@@ -51,19 +47,20 @@ allows you to inject ``route`` ZCML directives into your application's
:mod:`repoze.bfg`.
When any ``route`` ZCML directive is present in an application's
-``configure.zcml``, "under the hood" :mod:`repoze.bfg` wraps the "root
-factory" in a special ``RoutesRootFactory`` instance. The wrapper
-instance then acts as the root factory. When it acts as a root
-factory, it is willing to check the requested URL against a *routes
-map* to find the :term:`context` and the :term:`view name` before
-traversal has a chance to find it first. If it finds a context and a
-view name via a route, :mod:`repoze.bfg` will attempt to look up and
-call a :mod:`repoze.bfg` :term:`view` that matches the context and the
-view name. If no route matches, :mod:`repoze.bfg` will fail over to
-calling the root factory callable passed to the application in it's
-``make_app`` function (usually a traversal function). By configuring
-your ZCML ``route`` statements appropriately, you can mix and match
-URL dispatch and traversal in this way.
+``configure.zcml``, "under the hood" :mod:`repoze.bfg` wraps the
+:term:`root factory` in a special ``RoutesRootFactory`` instance. The
+wrapper instance then acts as the effective root factory. When it
+acts as a root factory, it is willing to check the requested URL
+against a *routes map* to find a :term:`context` and a :term:`view`
+before traversal has a chance to find it first. If a route matches, a
+:term:`context` is generated and :mod:`repoze.bfg` will call the
+:term:`view` specified with the context and the request.
+
+If no route matches, :mod:`repoze.bfg` will fail over to calling the
+root factory callable passed to the application in it's ``make_app``
+function (usually a traversal function). By configuring your ZCML
+``route`` statements appropriately, you can mix and match URL dispatch
+and traversal in this way.
A root factory is not required for purely URL-dispatch-based apps: if
the root factory callable is ``None``, :mod:`repoze.bfg` will return a
@@ -88,25 +85,27 @@ name
The `route name
<http://routes.groovie.org/manual.html#route-name>`_,
- e.g. ``myroute``.
+ e.g. ``myroute``. This attribute is required.
-view_name
+view
- The :mod:`repoze.bfg` :term:`view name` that should be looked up
- when this route matches a URL.
+ The Python dotted-path name to a function that will be used as a
+ view callable when this route matches.
+ e.g. ``mypackage.views.my_view``. This attribute is required.
-factory
+permission
- The Python dotted-path name to a function that will generate a
- :mod:`repoze.bfg` context object when this route matches. By
- default, a ``repoze.bfg.urldispatch.DefaultRoutesContext`` object
- will be constructed if a factory is not provided.
+ The permission name required to invoke the view.
+ e.g. ``edit``. (see :ref:`using_security_with_urldispatch` for more
+ information about permissions).
-provides
+factory
- One or more Python-dotted path names to :term:`interface` objects
- that the context should be decorated with when it's constructed
- (allowing it to be found by a particular view lookup).
+ The Python dotted-path name to a function that will generate a
+ :mod:`repoze.bfg` context object when this route matches.
+ e.g. ``mypackage.models.MyFactoryClass``. By default, a
+ ``repoze.bfg.urldispatch.DefaultRoutesContext`` object will be
+ constructed if a factory is not provided.
encoding
@@ -179,39 +178,85 @@ that allows you to specify Routes `requirement
For example:
.. code-block:: xml
+ :linenos:
- <route path="archives/:year/:month">
+ <route
+ name="archive"
+ path="archives/:year/:month"
+ view=".views.archive_view">
<requirement
attr="year"
- expr="d{2,4}"/>
+ expr="d{2,4}"
+ />
<requirement
attr="month"
- expr="d{1,2}"/>
+ expr="d{1,2}"
+ />
</route>
Example 1
---------
-Below is an example of some route statements you might add to your
-``configure.zcml``:
+The simplest route delcaration:
.. code-block:: xml
:linenos:
<route
+ name="idea"
+ path="hello.html"
+ view="mypackage.views.hello_view"
+ />
+
+When the URL matches ``/hello.html``, the view callable at the Python
+dotted path name ``mypackage.views.hello_view`` will be called with a
+default context object and the request. See :ref:`views_chapter` for
+more information about views.
+
+The ``mypackage.views`` module referred to above might look like so:
+
+.. code-block:: python
+ :linenos:
+
+ from webob import Response
+
+ def hello_view(context, request):
+ return Response('Hello!')
+
+In this case the context object passed to the view will be an instance
+of the ``repoze.bfg.urldispatch.DefaultRoutesContext``. This is the
+type of obejct created for a context when there is no "factory"
+specified in the ``route`` declaration.
+
+Example 2
+---------
+
+Below is an example of some more complicated route statements you
+might add to your ``configure.zcml``:
+
+.. code-block:: xml
+ :linenos:
+
+ <route
+ name="idea"
path="ideas/:idea"
- view_name="ideas"/>
+ view="mypackage.views.idea_view"
+ />
<route
+ name="user"
path="users/:user"
- view_name="users"/>
+ view="mypackage.views.user_view"
+ />
- <route
+ <route
+ name="tag"
path="tags/:tag"
- view_name="tags"/>
+ view="mypackage.views.tag_view"
+ />
The above configuration will allow :mod:`repoze.bfg` to service URLs
in these forms:
@@ -224,10 +269,12 @@ in these forms:
/tags/<tagname>
When a URL matches the pattern ``/ideas/<ideaname>``, the view
-registered with the name ``ideas`` for the interface
-``repoze.bfg.interfaces.IRoutesContext`` will be called. An error
-will be raised if no view can be found with that interface type and
-view name combination.
+registered with the name ``idea`` will be called. This will be the
+view available at the dotted Python pathname
+``mypackage.views.idea_view``.
+
+Example 3
+---------
The context object passed to a view found as the result of URL
dispatch will by default be an instance of the
@@ -243,46 +290,31 @@ An example of using a route with a factory:
:linenos:
<route
+ name="idea"
path="ideas/:idea"
+ view=".views.idea_view"
factory=".models.Idea"
- view_name="ideas"/>
+ />
The above route will manufacture an ``Idea`` model as a context,
-assuming that ``.models.Idea`` resolves to a class that accepts
-arbitrary key/value pair arguments.
+assuming that ``mypackage.models.Idea`` resolves to a class that
+accepts arbitrary key/value pair arguments.
.. note:: Values prefixed with a period (``.``) for the ``factory``
and ``provides`` attributes of a ``route`` (such as
- ``.models.Idea`` above) mean "relative to the Python package
- directory in which this :term:`ZCML` file is stored". So if the
- above ``route`` declaration was made inside a ``configure.zcml``
- file that lived in the ``hello`` package, you could replace the
- relative ``.models.Idea`` with the absolute ``hello.models.Idea``
- Either the relative or absolute form is functionally equivalent.
- It's often useful to use the relative form, in case your package's
- name changes. It's also shorter to type.
+ ``.models.Idea`` and ``.views.idea_view``) above) mean "relative to
+ the Python package directory in which this :term:`ZCML` file is
+ stored". So if the above ``route`` declaration was made inside a
+ ``configure.zcml`` file that lived in the ``hello`` package, you
+ could replace the relative ``.models.Idea`` with the absolute
+ ``hello.models.Idea`` Either the relative or absolute form is
+ functionally equivalent. It's often useful to use the relative
+ form, in case your package's name changes. It's also shorter to
+ type.
All context objects manufactured via URL dispatch will be decorated by
default with the ``repoze.bfg.interfaces.IRoutesContext``
-:term:`interface`. To decorate a context found via a route with other
-interfaces, you can use a ``provides`` attribute on the ZCML
-statement. It should be a space-separated list of dotted Python names
-that point at interface definitions.
-
-An example of using a route with a set of ``provides`` interfaces:
-
-.. code-block:: xml
- :linenos:
-
- <route
- path="ideas/:idea"
- provides=".interfaces.IIdea .interfaces.IContent"
- view_name="ideas"/>
-
-The above route will manufacture an instance of
-``DefaultRoutesContext`` as a context; it will be decorate with the
-``.interfaces.IIdea`` and ``.interfaces.IContent`` interfaces, as long
-as those dotted names resolve to interfaces.
+:term:`interface`.
If no route matches in the above configuration, :mod:`repoze.bfg` will
call the "fallback" ``get_root`` callable provided to it during
@@ -294,7 +326,7 @@ error will be raised when no route matches.
context. You can also map classes to views; interfaces are
not used then.
-Example 2
+Example 4
---------
An example of configuring a ``view`` declaration in ``configure.zcml``
@@ -304,24 +336,14 @@ function is as follows:
.. code-block:: xml
:linenos:
- <view
- for=".interfaces.ISomeContext"
- view=".views.articles_view"
- name="articles"
- />
-
<route
+ name="article"
path="archives/:article"
- view_name="articles"
+ view=".views.article_view"
factory=".models.Article"
- provides=".interfaces.ISomeContext"
/>
-All context objects found via Routes URL dispatch will provide the
-``IRoutesContext`` interface (attached dynamically). The above
-``route`` statement will also cause contexts generated by the route to
-have the ``.interfaces.ISomeContext`` interface as well. The
-``.models`` modulemight look like so:
+The ``.models`` module referred to above might look like so:
.. code-block:: python
:linenos:
@@ -330,6 +352,16 @@ have the ``.interfaces.ISomeContext`` interface as well. The
def __init__(self, **kw):
self.__dict__.update(kw)
+The ``.views`` module referred to above might look like so:
+
+.. code-block:: python
+ :linenos:
+
+ from webob import Response
+
+ def article_view(context, request):
+ return Response('Article with name' % context.article)
+
The effect of this configuration: when this :mod:`repoze.bfg`
application runs, if any URL matches the pattern
``archives/:article``, the ``.views.articles_view`` view will be
@@ -343,29 +375,6 @@ In this case in particular, when a user visits
Article class and it will have an ``article`` attribute with the value
of ``something``.
-Example 3
----------
-
-You can also make the ``view_name`` into a routes path argument
-instead of specifying it as an argument:
-
-.. code-block:: xml
- :linenos:
-
- <view
- for="repoze.bfg.interfaces.IRoutesContext"
- view=".views.articles_view"
- name="articles"
- />
-
- <route
- path="archives/:view_name"
- />
-
-When you do this, the :term:`view name` will be computed dynamically if
-the route matches. In the above example, if the ``view_name`` turns
-out to be ``articles``, the articles view will eventually be called.
-
Catching the Root URL
---------------------
@@ -379,7 +388,7 @@ declaration:
<route
path=""
name="root"
- view_name="root_view"
+ view=".views.root_view"
/>
Cleaning Up After a Request
@@ -425,6 +434,8 @@ Then in the ``configure.zcml`` of your package, inject the following:
This will cause the DBSession to be removed whenever the WSGI
environment is destroyed (usually at the end of every request).
+.. _using_security_with_urldispatch:
+
Using :mod:`repoze.bfg` Security With URL Dispatch
--------------------------------------------------
@@ -471,9 +482,3 @@ the ``Article`` class' constructor, too.
:term:`Routes` manual for a general overview of what the
``condition`` argument to ``.connect`` does.
-Further Documentation and Examples
-----------------------------------
-
-The API documentation in :ref:`urldispatch_module` documents an older
-(now-deprecated) version of Routes support in :mod:`repoze.bfg`.
-