summaryrefslogtreecommitdiff
path: root/docs/narr/urldispatch.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/narr/urldispatch.rst')
-rw-r--r--docs/narr/urldispatch.rst505
1 files changed, 187 insertions, 318 deletions
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 76eca454d..ca8fe84f3 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -6,16 +6,28 @@
URL Dispatch
============
-: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`.
+:term:`URL dispatch` provides a simple way to map URLs to :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.
+
+:term:`URL dispatch` is one of two ways to perform :term:`resource
+location` in :app:`Pyramid`; the other way is using :term:`traversal`.
+If no route is matched using :term:`URL dispatch`, :app:`Pyramid` falls
+back to :term:`traversal` to handle the :term:`request`.
+
+It is the responsibility of the :term:`resource location` subsystem
+(i.e., :term:`URL dispatch` or :term:`traversal`) to find the resource
+object that is the :term:`context` of the :term:`request`. Once the
+:term:`context` is determined, :term:`view lookup` is then responsible
+for finding and invoking a :term:`view callable`. A view callable is a
+specific bit of code, defined in your application, that receives the
+:term:`request` and returns a :term:`response` object.
+
+Where appropriate, we will describe how view lookup interacts with
+:term:`resource location`. The :ref:`view_config_chapter` chapter describes
+the details of :term:`view lookup`.
High-Level Operational Overview
-------------------------------
@@ -24,10 +36,9 @@ If route configuration is present in an application, the :app:`Pyramid`
:term:`Router` checks every incoming request against an ordered set of URL
matching patterns present in a *route map*.
-If any route pattern matches the information in the :term:`request` provided
-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.
+If any route pattern matches the information in the :term:`request`,
+:app:`Pyramid` 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
@@ -72,8 +83,8 @@ example:
.. versionchanged:: 1.0a4
Prior to 1.0a4, routes allow for a marker starting with a ``:``, for
- example ``/prefix/:one/:two``. Starting in 1.0a4, this style is deprecated
- in favor or ``{}`` usage which allows for additional functionality.
+ example ``/prefix/:one/:two``. This style is now deprecated
+ in favor of ``{}`` usage which allows for additional functionality.
.. index::
single: route configuration; view callable
@@ -85,8 +96,7 @@ When a route configuration declaration names a ``view`` attribute, the value
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`.
+result of a request.
Here's an example route configuration that references a view callable:
@@ -115,49 +125,6 @@ When a route configuration names a ``view`` attribute, the :term:`view
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
-names a view callable as a ``view`` argument, and a request enters the system
-which matches the pattern of the route, the result is simple: the view
-callable associated with the route is invoked with the request that caused
-the invocation.
-
-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 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
-will always be found when the route pattern is matched during a request. To
-do so:
-
-- A special route-specific :term:`interface` is created at startup time for
- each route configuration declaration.
-
-- When a route configuration declaration mentions a ``view`` attribute, a
- :term:`view configuration` is registered at startup time. This view
- configuration uses the route-specific interface as a :term:`request` type.
-
-- At runtime, when a request causes any route to match, the :term:`request`
- object is decorated with the route-specific interface.
-
-- The fact that the request is decorated with a route-specific interface
- causes the view lookup machinery to always use the view callable registered
- using that interface by the route configuration to service requests that
- match the route pattern.
-
-In this way, we supply a shortcut to the developer. Under the hood, the
-:term:`resource location` and :term:`view lookup` subsystems provided by
-:app:`Pyramid` are still being utilized, but in a way which does not require
-a developer to understand either of them in detail. It also means that we
-can allow a developer to combine :term:`URL dispatch` and :term:`traversal`
-in various exceptional cases as documented in :ref:`hybrid_chapter`.
-
.. index::
single: route path pattern syntax
@@ -191,10 +158,12 @@ replacement marker (e.g. ``{foo}``) or a certain combination of both. A
replacement marker does not need to be preceded by a ``/`` character.
A replacement marker is in the format ``{name}``, where this means "accept
-any characters up to the next non-alphanumeric character and use this as the
-``name`` matchdict value." For example, the following pattern defines one
-literal segment ("foo") and two dynamic replacement markers ("baz", and
-"bar"):
+any characters up to the next slash character and use this as the ``name``
+:term:`matchdict` value." A matchdict is the dictionary representing the
+dynamic parts extracted from a URL based on the routing pattern. It is
+available as ``request.matchdict``. For example, the following pattern
+defines one literal segment (``foo``) and two replacement markers (``baz``,
+and ``bar``):
.. code-block:: text
@@ -236,8 +205,21 @@ To capture both segments, two replacement markers can be used:
The literal path ``/foo/biz.html`` will match the above route pattern, and
the match result will be ``{'name': 'biz', 'ext': 'html'}``. This occurs
-because the replacement marker ``{name}`` has a literal part of ``.``
-(period) between the other replacement marker ``{ext}``.
+because there is a literal part of ``.`` (period) between the two replacement
+markers ``{name}`` and ``{ext}``.
+
+Replacement markers can optionally specify a regular expression which will be
+used to decide whether a path segment should match the marker. To specify
+that a replacement marker should match only a specific set of characters as
+defined by a regular expression, you must use a slightly extended form of
+replacement marker syntax. Within braces, the replacement marker name must
+be followed by a colon, then directly thereafter, the regular expression.
+The *default* regular expression associated with a replacement marker
+``[^/]+`` matches one or more characters which are not a slash. For example,
+under the hood, the replacement marker ``{foo}`` can more verbosely be
+spelled as ``{foo:[^/]+}``. You can change this to be an arbitrary regular
+expression to match an arbitrary sequence of characters, such as
+``{foo:\d+}`` to match only digits.
It is possible to use two replacement markers without any literal characters
between them, for instance ``/{foo}{bar}``. However, this would be a
@@ -251,9 +233,9 @@ replacement marker. For example, for the URL ``/abc/``:
- ``/{foo}/`` will match.
-Note that values representing path segments matched with a ``{segment}``
-match will be url-unquoted and decoded from UTF-8 into Unicode within the
-matchdict. So for instance, the following pattern:
+Note that values representing matched path segments will be url-unquoted and
+decoded from UTF-8 into Unicode within the matchdict. So for instance, the
+following pattern:
.. code-block:: text
@@ -284,8 +266,11 @@ The above pattern will match these URLs, generating the following matchdicts:
.. code-block:: text
- foo/1/2/ -> {'baz':'1', 'bar':'2', 'fizzle':()}
- foo/abc/def/a/b/c -> {'baz':'abc', 'bar':'def', 'fizzle':('a', 'b', 'c')}
+ foo/1/2/ ->
+ {'baz':u'1', 'bar':u'2', 'fizzle':()}
+
+ foo/abc/def/a/b/c ->
+ {'baz':u'abc', 'bar':u'def', 'fizzle':(u'a', u'b', u'c')}
Note that when a ``*stararg`` remainder match is matched, the value put into
the matchdict is turned into a tuple of path segments representing the
@@ -320,8 +305,8 @@ The above pattern will match these URLs, generating the following matchdicts:
.. code-block:: text
- foo/1/2/ -> {'baz':'1', 'bar':'2', 'fizzle':()}
- foo/abc/def/a/b/c -> {'baz':'abc', 'bar':'def', 'fizzle': 'a/b/c')}
+ foo/1/2/ -> {'baz':u'1', 'bar':u'2', 'fizzle':()}
+ foo/abc/def/a/b/c -> {'baz':u'abc', 'bar':u'def', 'fizzle': u'a/b/c')}
This occurs because the default regular expression for a marker is ``[^/]+``
which will match everything up to the first ``/``, while ``{fizzle:.*}`` will
@@ -343,7 +328,7 @@ are added to the application at startup time. This is unlike
:term:`traversal`, which depends on emergent behavior which happens as a
result of traversing a resource tree.
-For routes added via the :mod:`pyramid.config.Configurator.add_route` method,
+For routes added via the :mod:`~pyramid.config.Configurator.add_route` method,
the order that routes are evaluated is the order in which they are added to
the configuration imperatively.
@@ -388,7 +373,7 @@ In this way, each route can use a different factory, making it possible to
supply a different :term:`context` resource object to the view related to
each particular route.
-Supplying a different resource factory each route is useful when you're
+Supplying a different resource factory for each route is useful when you're
trying to use a :app:`Pyramid` :term:`authorization policy` to provide
declarative, "context sensitive" security checks; each resource can maintain
a separate :term:`ACL`, as documented in
@@ -400,12 +385,14 @@ Route Configuration Arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Route configuration ``add_route`` statements may specify a large number of
-arguments.
+arguments. They are documented as part of the API documentation at
+:meth:`pyramid.config.Configurator.add_route`.
Many of these arguments are :term:`route predicate` arguments. A route
predicate argument specifies that some aspect of the request must be true for
the associated route to be considered a match during the route matching
-process.
+process. Examples of route predicate arguments are ``pattern``, ``xhr``, and
+``request_method``.
Other arguments are view configuration related arguments. These only have an
effect when the route configuration names a ``view``.
@@ -413,201 +400,13 @@ effect when the route configuration names a ``view``.
Other arguments are ``name`` and ``factory``. These arguments represent
neither predicates nor view configuration information.
-**Non-Predicate Arguments**
-
-``name``
- The name of the route, e.g. ``myroute``. This attribute is required. It
- must be unique among all defined routes in a given application.
-
-``factory``
- A Python object (often a function or a class) or a :term:`dotted Python
- name` to such an object that will generate a :app:`Pyramid` resource object
- as the :term:`root` when this route matches. For example,
- ``mypackage.resources.MyFactoryClass``. If this argument is not specified,
- the traversal root factory will be used.
-
-``traverse``
- If you would like to cause the :term:`context` resource to be something
- other than the :term:`root` resource object when this route matches, you
- can spell a traversal pattern as the ``traverse`` argument. This traversal
- pattern will be used as the traversal path: traversal will begin at the
- root object implied by this route (either the global root, or the object
- returned by the ``factory`` associated with this route).
-
- The syntax of the ``traverse`` argument is the same as it is for
- ``pattern``. For example, if the ``pattern`` provided is
- ``articles/{article}/edit``, and the ``traverse`` argument provided is
- ``/{article}``, when a request comes in that causes the route to match in
- such a way that the ``article`` match value is '1' (when the request URI is
- ``/articles/1/edit``), the traversal path will be generated as ``/1``.
- This means that the root object's ``__getitem__`` will be called with the
- name ``1`` during the traversal phase. If the ``1`` object exists, it will
- become the :term:`context` resource of the request.
- :ref:`traversal_chapter` has more information about traversal.
-
- If the traversal path contains segment marker names which are not present
- in the ``pattern`` argument, a runtime error will occur. The ``traverse``
- pattern should not contain segment markers that do not exist in the
- ``pattern``.
-
- A similar combining of routing and traversal is available when a route is
- matched which contains a ``*traverse`` remainder marker in its pattern (see
- :ref:`using_traverse_in_a_route_pattern`). The ``traverse`` argument
- allows you to associate route patterns with an arbitrary traversal path
- without using a a ``*traverse`` remainder marker; instead you can use other
- match information.
-
- Note that the ``traverse`` argument is ignored when attached to a route
- that has a ``*traverse`` remainder marker in its pattern.
-
-**Predicate Arguments**
-
-``pattern``
- The path of the route e.g. ``ideas/{idea}``. This argument is required.
- See :ref:`route_path_pattern_syntax` for information about the syntax of
- route paths. If the path doesn't match the current URL, route matching
- continues.
-
- .. note:: In earlier releases of this framework, this argument existed
- as ``path``. ``path`` continues to work as an alias for
- ``pattern``.
-
-``xhr``
- This value should be either ``True`` or ``False``. If this value is
- specified and is ``True``, the :term:`request` must possess an
- ``HTTP_X_REQUESTED_WITH`` (aka ``X-Requested-With``) header for this route
- to match. This is useful for detecting AJAX requests issued from jQuery,
- Prototype and other Javascript libraries. If this predicate returns
- ``False``, route matching continues.
-
-``request_method``
- A string representing an HTTP method name, e.g. ``GET``, ``POST``,
- ``HEAD``, ``DELETE``, ``PUT``. If this argument is not specified, this
- route will match if the request has *any* request method. If this
- predicate returns ``False``, route matching continues.
-
-``path_info``
- This value represents a regular expression pattern that will be tested
- against the ``PATH_INFO`` WSGI environment variable. If the regex matches,
- this predicate will return ``True``. If this predicate returns ``False``,
- route matching continues.
-
-``request_param``
- This value can be any string. A view declaration with this argument
- ensures that the associated route will only match when the request has a
- key in the ``request.params`` dictionary (an HTTP ``GET`` or ``POST``
- variable) that has a name which matches the supplied value. If the value
- supplied as the argument has a ``=`` sign in it,
- e.g. ``request_params="foo=123"``, then the key (``foo``) must both exist
- in the ``request.params`` dictionary, and the value must match the right
- hand side of the expression (``123``) for the route to "match" the current
- request. If this predicate returns ``False``, route matching continues.
-
-``header``
- This argument represents an HTTP header name or a header name/value pair.
- If the argument contains a ``:`` (colon), it will be considered a
- name/value pair (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``). If
- the value contains a colon, the value portion should be a regular
- expression. If the value does not contain a colon, the entire value will
- be considered to be the header name (e.g. ``If-Modified-Since``). If the
- value evaluates to a header name only without a value, the header specified
- by the name must be present in the request for this predicate to be true.
- If the value evaluates to a header name/value pair, the header specified by
- the name must be present in the request *and* the regular expression
- specified as the value must match the header value. Whether or not the
- value represents a header name or a header name/value pair, the case of the
- header name is not significant. If this predicate returns ``False``, route
- matching continues.
-
-``accept``
- This value represents a match query for one or more mimetypes in the
- ``Accept`` HTTP request header. If this value is specified, it must be in
- one of the following forms: a mimetype match token in the form
- ``text/plain``, a wildcard mimetype match token in the form ``text/*`` or a
- match-all wildcard mimetype match token in the form ``*/*``. If any of the
- forms matches the ``Accept`` header of the request, this predicate will be
- true. If this predicate returns ``False``, route matching continues.
-
-``custom_predicates``
- This value should be a sequence of references to custom predicate
- callables. Use custom predicates when no set of predefined predicates does
- what you need. Custom predicates can be combined with predefined
- predicates as necessary. Each custom predicate callable should accept two
- arguments: ``context`` and ``request`` and should return either ``True`` or
- ``False`` after doing arbitrary evaluation of the context resource and/or
- the request. If all callables return ``True``, the associated route will
- be considered viable for a given request. If any custom predicate returns
- ``False``, route matching continues. Note that the value ``context`` will
- always be ``None`` when passed to a custom route predicate.
-
-**View-Related Arguments**
-
-``view``
- A Python object or a :term:`dotted Python name` to such an object that will
- be used as a view callable when this route
- matches. e.g. ``mypackage.views.my_view``.
-
-``view_context``
- A class or an :term:`interface` (or a :term:`dotted Python name` to such an
- object) that the :term:`context` resource should possess for the view named
- by the route to be used. If this attribute is not specified, the default
- (``None``) will be used.
-
- If the ``view`` argument is not provided, this argument has no effect.
-
- This attribute can also be spelled as ``for_`` or ``view_for``.
-
-``view_permission``
- The permission name required to invoke the view associated with this route.
- e.g. ``edit``. (see :ref:`using_security_with_urldispatch` for more
- information about permissions).
-
- If the ``view`` attribute is not provided, this argument has no effect.
-
- This argument can also be spelled as ``permission``.
-
-``view_renderer``
- This is either a single string term (e.g. ``json``) or a string implying a
- path or :term:`asset specification` (e.g. ``templates/views.pt``). If the
- renderer value is a single term (does not contain a dot ``.``), the
- specified term will be used to look up a renderer implementation, and that
- renderer implementation will be used to construct a response from the view
- return value. If the renderer term contains a dot (``.``), the specified
- term will be treated as a path, and the filename extension of the last
- element in the path will be used to look up the renderer implementation,
- which will be passed the full path. The renderer implementation will be
- used to construct a response from the view return value. See
- :ref:`views_which_use_a_renderer` for more information.
-
- If the ``view`` argument is not provided, this argument has no effect.
-
- This argument can also be spelled as ``renderer``.
-
-``view_attr``
- The view machinery defaults to using the ``__call__`` method of the view
- callable (or the function itself, if the view callable is a function) to
- obtain a response dictionary. The ``attr`` value allows you to vary the
- method attribute used to obtain the response. For example, if your view
- was a class, and the class has a method named ``index`` and you wanted to
- use this method instead of the class' ``__call__`` method to return the
- response, you'd say ``attr="index"`` in the view configuration for the
- view. This is most useful when the view definition is a class.
-
- If the ``view`` argument is not provided, this argument has no
- effect.
-
-``use_global_views``
- When a request matches this route, and view lookup cannot find a view which
- has a 'route_name' predicate argument that matches the route, try to fall
- back to using a view that otherwise matches the context and request.
-
.. _custom_route_predicates:
Custom Route Predicates
~~~~~~~~~~~~~~~~~~~~~~~
Each of the predicate callables fed to the ``custom_predicates`` argument of
-:meth:`pyramid.config.Configurator.add_route` must be a callable accepting
+:meth:`~pyramid.config.Configurator.add_route` must be a callable accepting
two arguments. The first argument passed to a custom predicate is a
dictionary conventionally named ``info``. The second argument is the current
:term:`request` object.
@@ -631,7 +430,7 @@ For example:
num_one_two_or_three = any_of('num', 'one', 'two', 'three')
- config.add_route('num', '/{num}',
+ config.add_route('route_to_num', '/{num}',
custom_predicates=(num_one_two_or_three,))
The above ``any_of`` function generates a predicate which ensures that the
@@ -641,7 +440,7 @@ predicate function named ``num_one_two_or_three``, which ensures that the
``num`` segment is one of the values ``one``, ``two``, or ``three`` , and use
the result as a custom predicate by feeding it inside a tuple to the
``custom_predicates`` argument to
-:meth:`pyramid.config.Configurator.add_route`.
+:meth:`~pyramid.config.Configurator.add_route`.
A custom route predicate may also *modify* the ``match`` dictionary. For
instance, a predicate might do some type conversion of values:
@@ -662,7 +461,7 @@ instance, a predicate might do some type conversion of values:
ymd_to_int = integers('year', 'month', 'day')
- config.add_route('num', '/{year}/{month}/{day}',
+ config.add_route('ymd', '/{year}/{month}/{day}',
custom_predicates=(ymd_to_int,))
Note that a conversion predicate is still a predicate so it must return
@@ -685,7 +484,7 @@ expressions specifying requirements for that marker. For instance:
ymd_to_int = integers('year', 'month', 'day')
- config.add_route('num', '/{year:\d+}/{month:\d+}/{day:\d+}',
+ config.add_route('ymd', '/{year:\d+}/{month:\d+}/{day:\d+}',
custom_predicates=(ymd_to_int,))
Now the try/except is no longer needed because the route will not match at
@@ -795,7 +594,7 @@ The Matched Route
When the URL pattern associated with a particular route configuration is
matched by a request, an object named ``matched_route`` is added as an
attribute of the :term:`request` object. Thus, ``request.matched_route``
-will be an object implementing the :class:`pyramid.interfaces.IRoute`
+will be an object implementing the :class:`~pyramid.interfaces.IRoute`
interface which matched the request. The most useful attribute of the route
object is ``name``, which is the name of the route that matched.
@@ -854,7 +653,8 @@ The ``mypackage.views`` module referred to above might look like so:
The view has access to the matchdict directly via the request, and can access
variables within it that match keys present as a result of the route pattern.
-See :ref:`views_chapter` for more information about views.
+See :ref:`views_chapter`, and :ref:`view_config_chapter` for more
+information about views.
Example 2
~~~~~~~~~
@@ -907,7 +707,7 @@ the :term:`root factory` configured at startup time (the ``root_factory``
argument to the :term:`Configurator` used to configure the application).
You can override this behavior by passing in a ``factory`` argument to the
-:meth:`pyramid.config.Configurator.add_route` method for a particular route.
+:meth:`~pyramid.config.Configurator.add_route` method for a particular route.
The ``factory`` should be a callable that accepts a :term:`request` and
returns an instance of a class that will be the context resource used by the
view.
@@ -972,7 +772,7 @@ Matching the Root URL
It's not entirely obvious how to use a route pattern to match the root URL
("/"). To do so, give the empty string as a pattern in a call to
-:meth:`pyramid.config.Configurator.add_route`:
+:meth:`~pyramid.config.Configurator.add_route`:
.. code-block:: python
:linenos:
@@ -1005,8 +805,9 @@ route patterns. For example, if you've configured a route with the ``name``
url = route_url('foo', request, a='1', b='2', c='3')
This would return something like the string ``http://example.com/1/2/3`` (at
-least if the current protocol and hostname implied ``http:/example.com``).
-See the :func:`pyramid.url.route_url` API documentation for more information.
+least if the current protocol and hostname implied ``http://example.com``).
+See the :func:`~pyramid.url.route_url` API documentation for more
+information.
.. index::
single: redirecting to slash-appended routes
@@ -1033,8 +834,10 @@ route configuration looks like so:
.. code-block:: python
:linenos:
- config.add_route('noslash', 'no_slash', view='myproject.views.no_slash')
- config.add_route('hasslash', 'has_slash/', view='myproject.views.has_slash')
+ config.add_route('noslash', 'no_slash',
+ view='myproject.views.no_slash')
+ config.add_route('hasslash', 'has_slash/',
+ view='myproject.views.has_slash')
If a request enters the application with the ``PATH_INFO`` value of
``/has_slash/``, the second route will match. If a request enters the
@@ -1109,16 +912,7 @@ Cleaning Up After a Request
---------------------------
Sometimes it's required that some cleanup be performed at the end of a
-request when a database connection is involved. When :term:`traversal` is
-used, this cleanup is often done as a side effect of the traversal
-:term:`root factory`. Often the root factory will insert an object into the
-WSGI environment that performs some cleanup when its ``__del__`` method is
-called. When URL dispatch is used, however, no special root factory is
-required, so sometimes that option is not open to you.
-
-Instead of putting this cleanup logic in the root factory, however, you can
-cause a subscriber to be fired when a new request is detected; the subscriber
-can do this work.
+request when a database connection is involved.
For example, let's say you have a ``mypackage`` :app:`Pyramid` application
package that uses SQLAlchemy, and you'd like the current SQLAlchemy database
@@ -1129,37 +923,32 @@ session to be removed after each request. Put the following in the
.. code-block:: python
:linenos:
- from mypackage.sql import DBSession
-
- class Cleanup:
- def __init__(self, cleaner):
- self.cleaner = cleaner
- def __del__(self):
- self.cleaner()
-
- def handle_teardown(event):
- environ = event.request.environ
- environ['mypackage.sqlcleaner'] = Cleanup(DBSession.remove)
+ from mypackage.models import DBSession
-Then add an event subscriber in your startup configuration:
+ from pyramid.events import subscriber
+ from pyramid.events import NewRequest
-.. code-block:: python
- :linenos:
+ def cleanup_callback(request):
+ DBSession.remove()
- config.add_subscriber('mypackage.handle_teardown',
- 'pyramid.events.NewRequest')
+ @subscriber(NewRequest)
+ def add_cleanup_callback(event):
+ event.request.add_finished_callback(cleanup_callback)
-Registering a handle_teardown subscriber will cause the DBSession to be
-removed whenever the WSGI environment is destroyed (usually at the end of
-every request).
+Registering the ``cleanup_callback`` finished callback at the start of a
+request (by causing the ``add_cleanup_callback`` to receive a
+:class:`pyramid.events.NewRequest` event at the start of each request) will
+cause the DBSession to be removed whenever request processing has ended.
+Note that in the example above, for the :class:`pyramid.events.subscriber`
+decorator to "work", the :meth:`pyramid.config.Configurator.scan` method must
+be called against your ``mypackage`` package during application
+initialization.
-.. note:: This is only an example. In particular, it is not necessary
- to cause ``DBSession.remove`` to be called as the result of an
- event listener in an application generated from any
- :app:`Pyramid` paster template, because these all use the
- ``repoze.tm2`` middleware. The cleanup done by
- ``DBSession.remove`` is unnecessary when ``repoze.tm2`` middleware
- is in the WSGI pipeline.
+.. note:: This is only an example. In particular, it is not necessary to
+ cause ``DBSession.remove`` to be called in an application generated from
+ any :app:`Pyramid` paster template, because these all use the
+ ``repoze.tm2`` middleware. The cleanup done by ``DBSession.remove`` is
+ unnecessary when ``repoze.tm2`` middleware is in the WSGI pipeline.
.. index::
pair: URL dispatch; security
@@ -1231,12 +1020,92 @@ which you started the application from. For example:
See :ref:`environment_chapter` for more information about how, and where to
set these values.
+.. index::
+ pair: routes; printing
+ single: paster proutes
+
+.. _displaying_application_routes:
+
+Displaying All Application Routes
+---------------------------------
+
+You can use the ``paster proutes`` command in a terminal window to print a
+summary of routes related to your application. Much like the ``paster
+pshell`` command (see :ref:`interactive_shell`), the ``paster proutes``
+command accepts two arguments. The first argument to ``proutes`` is the path
+to your application's ``.ini`` file. The second is the ``app`` section name
+inside the ``.ini`` file which points to your application.
+
+For example:
+
+.. code-block:: text
+ :linenos:
+
+ [chrism@thinko MyProject]$ ../bin/paster proutes development.ini MyProject
+ Name Pattern View
+ ---- ------- ----
+ home / <function my_view>
+ home2 / <function my_view>
+ another /another None
+ static/ static/*subpath <static_view object>
+ catchall /*subpath <function static_view>
+
+``paster proutes`` generates a table. The table has three columns: a Name
+name column, a Pattern column, and a View column. The items listed in the
+Name column are route names, the items listen in the Pattern column are route
+patterns, and the items listed in the View column are representations of the
+view callable that will be invoked when a request matches the associated
+route pattern. The view column may show ``None`` if no associated view
+callable could be found. If no routes are configured within your
+application, nothing will be printed to the console when ``paster proutes``
+is executed.
+
+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
+names a view callable as a ``view`` argument, and a request enters the system
+which matches the pattern of the route, the result is simple: the view
+callable associated with the route is invoked with the request that caused
+the invocation.
+
+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 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
+will always be found when the route pattern is matched during a request. To
+do so:
+
+- A special route-specific :term:`interface` is created at startup time for
+ each route configuration declaration.
+
+- When a route configuration declaration mentions a ``view`` attribute, a
+ :term:`view configuration` is registered at startup time. This view
+ configuration uses the route-specific interface as a :term:`request` type.
+
+- At runtime, when a request causes any route to match, the :term:`request`
+ object is decorated with the route-specific interface.
+
+- The fact that the request is decorated with a route-specific interface
+ causes the view lookup machinery to always use the view callable registered
+ using that interface by the route configuration to service requests that
+ match the route pattern.
+
+In this way, we supply a shortcut to the developer. Under the hood, the
+:term:`resource location` and :term:`view lookup` subsystems provided by
+:app:`Pyramid` are still being utilized, but in a way which does not require
+a developer to understand either of them in detail. It also means that we
+can allow a developer to combine :term:`URL dispatch` and :term:`traversal`
+in various exceptional cases as documented in :ref:`hybrid_chapter`.
+
References
----------
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`).
-