diff options
Diffstat (limited to 'docs/narr/urldispatch.rst')
| -rw-r--r-- | docs/narr/urldispatch.rst | 227 |
1 files changed, 110 insertions, 117 deletions
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index 739a826c1..b7164ec40 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -6,33 +6,32 @@ URL Dispatch ============ -The URL dispatch feature of :app:`Pyramid` allows you to either -augment or replace :term:`traversal` as a :term:`context finding` -mechanism, allowing URL pattern matching to have the "first crack" at -resolving a given URL to :term:`context` and :term:`view name`. +The URL dispatch feature of :app:`Pyramid` allows you to either augment or +replace :term:`traversal` as a :term:`resource location` mechanism, allowing +URL pattern matching to have the "first crack" at resolving a given URL to +:term:`context` resource. -Although it is a "context-finding" mechanism, ironically, using URL -dispatch exclusively allows you to avoid thinking about your -application in terms of "contexts" and "view names" entirely. +Although it is a "resource-location" mechanism, ironically, using URL +dispatch exclusively allows you to avoid thinking about your application in +terms of resources entirely. Many applications don't need :app:`Pyramid` features -- such as context-sensitive declarative security via an :term:`authorization policy` -- -that benefit from having any visible separation between :term:`context -finding` and :term:`view lookup`. To this end, URL dispatch provides a handy -syntax that allows you to effectively map URLs *directly* to :term:`view` -code in such a way that you needn't think about your application in terms of -"context finding" at all. This makes developing a :app:`Pyramid` application -seem more like developing an application in a system that is "context-free", -such as :term:`Pylons` or :term:`Django`. - -Whether or not you care about "context", it often makes a lot of sense -to use :term:`URL dispatch` instead of :term:`traversal` in an -application that has no natural data hierarchy. For instance, if all -the data in your application lives in a relational database, and that -relational database has no self-referencing tables that form a natural -hierarchy, URL dispatch is easier to use than traversal, and is often -a more natural fit for creating an application that manipulates "flat" -data. +that benefit from having any visible separation between :term:`resource +location` and :term:`view lookup`. To this end, URL dispatch provides a +handy syntax that allows you to effectively map URLs *directly* to +:term:`view` code in such a way that you needn't think about your application +in terms of "resource location" at all. This makes developing a +:app:`Pyramid` application seem more like developing an application in a +system that is "resource-free", such as :term:`Pylons` or :term:`Django`. + +Whether or not you care about "resources", it often makes a lot of sense to +use :term:`URL dispatch` instead of :term:`traversal` in an application that +has no natural data hierarchy. For instance, if all the data in your +application lives in a relational database, and that relational database has +no self-referencing tables that form a natural hierarchy, URL dispatch is +easier to use than traversal, and is often a more natural fit for creating an +application that manipulates "flat" data. The presence of calls to the :meth:`pyramid.config.Configurator.add_route` method in imperative @@ -47,22 +46,21 @@ dispatch`. High-Level Operational Overview ------------------------------- -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 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`, a route-specific :term:`context` and -:term:`view name` will be generated. In this circumstance, -:app:`Pyramid` will shortcut :term:`traversal`, and will invoke -:term:`view lookup` using the context and view name generated by URL -dispatch. If the matched route names a :term:`view callable` in its -configuration, that view callable will be invoked when view lookup is -performed. +If any route pattern matches the information in the :term:`request` provided +to :app:`Pyramid`, a route-specific :term:`context` resource and :term:`view +name` will be generated. In this circumstance, :app:`Pyramid` will shortcut +:term:`traversal`, and will invoke :term:`view lookup` using the context +resource and view name generated by URL dispatch. If the matched route names +a :term:`view callable` in its configuration, that view callable will be +invoked when view lookup is performed. -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 perform context finding and view lookup. +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 +perform resource location and view lookup. Route Configuration ------------------- @@ -140,13 +138,12 @@ 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. -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:`context finding` and :term:`view -lookup`. When a route names a view callable, 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. +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, 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, @@ -179,7 +176,7 @@ during a request. To do so: to service requests that match the route pattern. In this way, we supply a shortcut to the developer. Under the hood, -the :term:`context finding` and :term:`view lookup` subsystems +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 @@ -402,13 +399,12 @@ will never be evaluated. Route Factories ~~~~~~~~~~~~~~~ -A "route" configuration declaration can mention a "factory". When -that route matches a request, and a factory is attached to a route, -the :term:`root factory` passed at startup time to the -:term:`Configurator` is ignored; instead the factory associated with -the route is used to generate a :term:`root` object. This object will -usually be used as the :term:`context` of the view callable ultimately -found via :term:`view lookup`. +A "route" configuration declaration can mention a "factory". When that route +matches a request, and a factory is attached to a route, the :term:`root +factory` passed at startup time to the :term:`Configurator` is ignored; +instead the factory associated with the route is used to generate a +:term:`root` object. This object will usually be used as the :term:`context` +resource of the view callable ultimately found via :term:`view lookup`. .. code-block:: python :linenos: @@ -419,17 +415,17 @@ found via :term:`view lookup`. The factory can either be a Python object or a :term:`dotted Python name` (a string) which points to such a Python object, as it is above. -In this way, each route can use a different factory, making it -possible to supply a different :term:`context` object to the view -related to each particular route. +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 context 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 context -can maintain a separate :term:`ACL`, as documented in -:ref:`using_security_with_urldispatch`. It is also useful when you -wish to combine URL dispatch with :term:`traversal` as documented -within :ref:`hybrid_chapter`. +Supplying a different context resource 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 +:ref:`using_security_with_urldispatch`. It is also useful when you wish to +combine URL dispatch with :term:`traversal` as documented within +:ref:`hybrid_chapter`. Route Configuration Arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -458,29 +454,28 @@ represent neither predicates nor view configuration information. ``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` :term:`context` object when this route + :app:`Pyramid` :term:`context` resource object 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` to be something other - than the :term:`root` 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). + 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` of the request. :ref:`traversal_chapter` has more - information about traversal. + ``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. @@ -576,7 +571,7 @@ represent neither predicates nor view configuration information. 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 and/or the request. If all callables + 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 @@ -646,10 +641,9 @@ represent neither predicates nor view configuration information. 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, - request, and view name (but does not match the route name predicate). + 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: @@ -798,13 +792,12 @@ request enters the system, for each route configuration declaration present in the system, :app:`Pyramid` checks the ``PATH_INFO`` against the pattern declared. -If any route matches, the route matching process stops. The -:term:`request` is decorated with a special :term:`interface` which -describes it as a "route request", the :term:`context` and :term:`view -name` are generated, and the context, the view name, and the resulting -request are handed off to :term:`view lookup`. This process is -otherwise known as :term:`context finding`. During view lookup, if -any ``view`` argument was provided within the matched route +If any route matches, the route matching process stops. The :term:`request` +is decorated with a special :term:`interface` which describes it as a "route +request", the :term:`context` resource is generated, and the context, the +view name, and the resulting request are handed off to :term:`view lookup`. +This process is otherwise known as :term:`resource location`. During view +lookup, if any ``view`` argument was provided within the matched route configuration, the :term:`view callable` it points to is called. When a route configuration is declared, it may contain :term:`route @@ -817,9 +810,9 @@ provided to a route configuration returns ``False``, that route is skipped and route matching continues through the ordered set of routes. -If no route matches after all route patterns are exhausted, -:app:`Pyramid` falls back to :term:`traversal` to do :term:`context -finding` and :term:`view lookup`. +If no route matches after all route patterns are exhausted, :app:`Pyramid` +falls back to :term:`traversal` to do :term:`resource location` and +:term:`view lookup`. .. index:: single: matchdict @@ -962,15 +955,16 @@ URL by the process will be passed to the view callable. Example 3 ~~~~~~~~~ -The context object passed in to a view found as the result of URL dispatch -will, by default, be an instance of the object returned by the :term:`root -factory` configured at startup time (the ``root_factory`` argument to the -:term:`Configurator` used to configure the application). +The context resource object passed in to a view found as the result of URL +dispatch will, by default, be an instance of the object returned by 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. The ``factory`` should be a callable that accepts a :term:`request` -and returns an instance of a class that will be the context used by the view. +: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. An example of using a route with a factory: @@ -981,9 +975,9 @@ An example of using a route with a factory: view='myproject.views.idea_view', factory='myproject.resources.Idea') -The above route will manufacture an ``Idea`` resource as a -:term:`context`, assuming that ``mypackage.resources.Idea`` resolves to a -class that accepts a request in its ``__init__``. For example: +The above route will manufacture an ``Idea`` resource as a :term:`context`, +assuming that ``mypackage.resources.Idea`` resolves to a class that accepts a +request in its ``__init__``. For example: .. code-block:: python :linenos: @@ -1237,13 +1231,13 @@ Using :app:`Pyramid` Security With URL Dispatch -------------------------------------------------- :app:`Pyramid` provides its own security framework which consults an -:term:`authorization policy` before allowing any application code to -be called. This framework operates in terms of an access control -list, which is stored as an ``__acl__`` attribute of a context object. -A common thing to want to do is to attach an ``__acl__`` to the -context object dynamically for declarative security purposes. You can -use the ``factory`` argument that points at a factory which attaches a -custom ``__acl__`` to an object at its creation time. +:term:`authorization policy` before allowing any application code to be +called. This framework operates in terms of an access control list, which is +stored as an ``__acl__`` attribute of a resource object. A common thing to +want to do is to attach an ``__acl__`` to the resource object dynamically for +declarative security purposes. You can use the ``factory`` argument that +points at a factory which attaches a custom ``__acl__`` to an object at its +creation time. Such a ``factory`` might look like so: @@ -1257,13 +1251,12 @@ Such a ``factory`` might look like so: if article == '1': self.__acl__ = [ (Allow, 'editor', 'view') ] -If the route ``archives/{article}`` is matched, and the article number -is ``1``, :app:`Pyramid` will generate an ``Article`` -:term:`context` with an ACL on it that allows the ``editor`` principal -the ``view`` permission. Obviously you can do more generic things -than inspect the routes match dict to see if the ``article`` argument -matches a particular string; our sample ``Article`` factory class is -not very ambitious. +If the route ``archives/{article}`` is matched, and the article number is +``1``, :app:`Pyramid` will generate an ``Article`` :term:`context` resource +with an ACL on it that allows the ``editor`` principal the ``view`` +permission. Obviously you can do more generic things than inspect the routes +match dict to see if the ``article`` argument matches a particular string; +our sample ``Article`` factory class is not very ambitious. .. note:: See :ref:`security_chapter` for more information about :app:`Pyramid` security and ACLs. |
