diff options
Diffstat (limited to 'docs/narr/urldispatch.rst')
| -rw-r--r-- | docs/narr/urldispatch.rst | 505 |
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`). - |
