diff options
| author | Chris McDonough <chrism@plope.com> | 2011-07-20 07:16:14 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-07-20 07:16:14 -0400 |
| commit | 8cb68208d42899b50025418812bb339f578d553f (patch) | |
| tree | c5c116c5f9b12db8c07219fbe5490bc29011ea76 /docs/narr | |
| parent | 6ce1e0cf1a141767ee0aca70786c15dd993347c5 (diff) | |
| download | pyramid-8cb68208d42899b50025418812bb339f578d553f.tar.gz pyramid-8cb68208d42899b50025418812bb339f578d553f.tar.bz2 pyramid-8cb68208d42899b50025418812bb339f578d553f.zip | |
- Reordered chapters in narrative section for better new user friendliness.
- Added more indexing markers to sections in documentation.
Diffstat (limited to 'docs/narr')
| -rw-r--r-- | docs/narr/firstapp.rst | 3 | ||||
| -rw-r--r-- | docs/narr/renderers.rst | 8 | ||||
| -rw-r--r-- | docs/narr/traversal.rst | 97 | ||||
| -rw-r--r-- | docs/narr/urldispatch.rst | 123 | ||||
| -rw-r--r-- | docs/narr/viewconfig.rst | 133 | ||||
| -rw-r--r-- | docs/narr/views.rst | 68 |
6 files changed, 198 insertions, 234 deletions
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst index 42711784b..6c53f3de0 100644 --- a/docs/narr/firstapp.rst +++ b/docs/narr/firstapp.rst @@ -322,6 +322,3 @@ see :class:`~pyramid.config.Configurator` . For more information about :term:`view configuration`, see :ref:`view_config_chapter`. -An example of using *declarative* configuration (:term:`ZCML`) instead of -imperative configuration to create a similar "hello world" is available -within the documentation for :term:`pyramid_zcml`. diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst index 572d5855e..801741c43 100644 --- a/docs/narr/renderers.rst +++ b/docs/narr/renderers.rst @@ -3,10 +3,10 @@ Renderers ========= -A view needn't *always* return a :term:`Response` object. If a view -happens to return something which does not implement the Pyramid -Response interface, :app:`Pyramid` will attempt to use a -:term:`renderer` to construct a response. For example: +A view callable needn't *always* return a :term:`Response` object. If a view +happens to return something which does not implement the Pyramid Response +interface, :app:`Pyramid` will attempt to use a :term:`renderer` to construct +a response. For example: .. code-block:: python :linenos: diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst index e1715dc25..aa36b4455 100644 --- a/docs/narr/traversal.rst +++ b/docs/narr/traversal.rst @@ -456,6 +456,103 @@ as the sole argument: ``request``; it is expected to return a response. -specific request attributes are also available as described in :ref:`special_request_attributes`. +.. index:: + single: resource interfaces + +.. _using_resource_interfaces: + +Using Resource Interfaces In View Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Instead of registering your views with a ``context`` that names a Python +resource *class*, you can optionally register a view callable with a +``context`` which is an :term:`interface`. An interface can be attached +arbitrarily to any resource object. View lookup treats context interfaces +specially, and therefore the identity of a resource can be divorced from that +of the class which implements it. As a result, associating a view with an +interface can provide more flexibility for sharing a single view between two +or more different implementations of a resource type. For example, if two +resource objects of different Python class types share the same interface, +you can use the same view configuration to specify both of them as a +``context``. + +In order to make use of interfaces in your application during view dispatch, +you must create an interface and mark up your resource classes or instances +with interface declarations that refer to this interface. + +To attach an interface to a resource *class*, you define the interface and +use the :func:`zope.interface.implements` function to associate the interface +with the class. + +.. code-block:: python + :linenos: + + from zope.interface import Interface + from zope.interface import implements + + class IHello(Interface): + """ A marker interface """ + + class Hello(object): + implements(IHello) + +To attach an interface to a resource *instance*, you define the interface and +use the :func:`zope.interface.alsoProvides` function to associate the +interface with the instance. This function mutates the instance in such a +way that the interface is attached to it. + +.. code-block:: python + :linenos: + + from zope.interface import Interface + from zope.interface import alsoProvides + + class IHello(Interface): + """ A marker interface """ + + class Hello(object): + pass + + def make_hello(): + hello = Hello() + alsoProvides(hello, IHello) + return hello + +Regardless of how you associate an interface, with a resource instance, or a +resource class, the resulting code to associate that interface with a view +callable is the same. Assuming the above code that defines an ``IHello`` +interface lives in the root of your application, and its module is named +"resources.py", the interface declaration below will associate the +``mypackage.views.hello_world`` view with resources that implement, or +provide, this interface. + +.. code-block:: python + :linenos: + + # config is an instance of pyramid.config.Configurator + + config.add_view('mypackage.views.hello_world', name='hello.html', + context='mypackage.resources.IHello') + +Any time a resource that is determined to be the :term:`context` provides +this interface, and a view named ``hello.html`` is looked up against it as +per the URL, the ``mypackage.views.hello_world`` view callable will be +invoked. + +Note, in cases where a view is registered against a resource class, and a +view is also registered against an interface that the resource class +implements, an ambiguity arises. Views registered for the resource class take +precedence over any views registered for any interface the resource class +implements. Thus, if one view configuration names a ``context`` of both the +class type of a resource, and another view configuration names a ``context`` +of interface implemented by the resource's class, and both view +configurations are otherwise identical, the view registered for the context's +class will "win". + +For more information about defining resources with interfaces for use within +view configuration, see :ref:`resources_which_implement_interfaces`. + + References ---------- diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index a25f47690..0598cd4f2 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -6,28 +6,12 @@ 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 to use :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`. +: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. A +view callable is a specific bit of code, defined in your application, that +receives the :term:`request` and returns a :term:`response` object. High-Level Operational Overview ------------------------------- @@ -37,18 +21,11 @@ If route configuration is present in an application, the :app:`Pyramid` matching patterns present in a *route map*. 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. +:app:`Pyramid` will invoke :term:`view lookup` to find a matching view. -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. - -Technically, URL dispatch is a :term:`resource location` mechanism (it finds -a context object). But ironically, using URL dispatch (instead of -:term:`traversal`) allows you to avoid thinking about your application in -terms of "resources" entirely, because it allows you to directly map a -:term:`view callable` to a route. +If no route pattern in the route map matches the information in the +:term:`request` provided in your application, :app:`Pyramid` will fail over +to using :term:`traversal` to perform resource location and view lookup. .. index:: single: route configuration @@ -89,8 +66,8 @@ example: When a :term:`view callable` added to the configuration by way of :meth:`~pyramid.config.Configurator.add_view` bcomes associated with a route -via its ``route_name`` predicate, that view callable will always be found -and invoked when the associated route pattern matches during a request. +via its ``route_name`` predicate, that view callable will always be found and +invoked when the associated route pattern matches during a request. More commonly, you will not use any ``add_view`` statements in your project's "setup" code, instead only using ``add_route`` statements using a @@ -323,12 +300,11 @@ Route Declaration Ordering Route configuration declarations are evaluated in a specific order when a request enters the system. As a result, the order of route configuration -declarations is very important. - -The order that routes declarations are evaluated is the order in which they -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. +declarations is very important. The order that routes declarations are +evaluated is the order in which they are added to the application at startup +time. (This is unlike a different way of mapping URLs to code that +:app:`Pyramid` provides, named :term:`traversal`, which does not depend on +pattern ordering). 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 @@ -551,27 +527,30 @@ Route Matching The main purpose of route configuration is to match (or not match) the ``PATH_INFO`` present in the WSGI environment provided during a request -against a URL path pattern. +against a URL path pattern. ``PATH_INFO`` represents the path portion of the +URL that was requested. The way that :app:`Pyramid` does this is very simple. When a 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` resource is generated, and the context and the -resulting request are handed off to :term:`view lookup`. During view lookup, -if a :term:`view callable` associated with the matched route is found, that -view is called. +:app:`Pyramid` checks the request's ``PATH_INFO`` against the pattern +declared. This checking happens in the order that the routes were declared +via :meth:`pyramid.config.Configurator.add_route`. When a route configuration is declared, it may contain :term:`route predicate` arguments. All route predicates associated with a route declaration must be ``True`` for the route configuration to be used for a -given request. - -If any predicate in the set of :term:`route predicate` arguments provided to -a route configuration returns ``False``, that route is skipped and route -matching continues through the ordered set of routes. +given request during a check. If any predicate in the set of :term:`route +predicate` arguments provided to a route configuration returns ``False`` +during a check, that route is skipped and route matching continues through +the ordered set of routes. + +If any route matches, the route matching process stops and the :term:`view +lookup` subsystem takes over to find the most reasonable view callable for +the matched route. Most often, there's only one view that will match (a view +configured with a ``route_name`` argument matching the matched route). To +gain a better understanding of how routes and views are associated in a real +application, you can use the ``paster pviews`` command, as documented in +:ref:`displaying_matching_views`. If no route matches after all route patterns are exhausted, :app:`Pyramid` falls back to :term:`traversal` to do :term:`resource location` and @@ -1083,24 +1062,28 @@ when the route pattern is matched during a request. To do so: 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`. - -To gain a better understanding of how routes and views are associated in a -real application, you can use the ``paster pviews`` command, as documented -in :ref:`displaying_matching_views`. + causes the :term:`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. + +As we can see from the above description, technically, URL dispatch doesn't +actually map a URL pattern directly to a view callable. Instead, URL +dispatch is a :term:`resource location` mechanism. A :app:`Pyramid` +:term:`resource location` subsystem (i.e., :term:`URL dispatch` or +:term:`traversal`) finds a :term:`resource` object that is the +:term:`context` of a :term:`request`. Once the :term:`context` is determined, +a separate subsystem named :term:`view lookup` is then responsible for +finding and invoking a :term:`view callable` based on information available +in the context and the request. When URL dispatch is used, the resource +location and 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. + +If no route is matched using :term:`URL dispatch`, :app:`Pyramid` falls back +to :term:`traversal` to handle the :term:`request`. References ---------- A tutorial showing how :term:`URL dispatch` can be used to create a :app:`Pyramid` application exists in :ref:`bfg_sql_wiki_tutorial`. - diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index 94b80a3f2..d776887c8 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -235,8 +235,10 @@ arguments that are supplied, the more specific, and narrower the usage of the configured view. ``name`` - The :term:`view name` required to match this view callable. Read - :ref:`traversal_chapter` to understand the concept of a view name. + The :term:`view name` required to match this view callable. A ``name`` + argument is typically only used when your application uses + :term:`traversal`. Read :ref:`traversal_chapter` to understand the concept + of a view name. If ``name`` is not supplied, the empty string is used (implying the default view). @@ -417,8 +419,7 @@ lives within a :app:`Pyramid` application module ``views.py``: from pyramid.view import view_config from pyramid.response import Response - @view_config(name='my_view', request_method='POST', context=MyResource, - permission='read') + @view_config(route_name='ok', request_method='POST', permission='read') def my_view(request): return Response('OK') @@ -429,9 +430,8 @@ configuration stanza: .. code-block:: python :linenos: - config.add_view('mypackage.views.my_view', name='my_view', - request_method='POST', context=MyResource, - permission='read') + config.add_view('mypackage.views.my_view', route_name='ok', + request_method='POST', permission='read') All arguments to ``view_config`` may be omitted. For example: @@ -499,7 +499,7 @@ If your view callable is a function, it may be used as a function decorator: from pyramid.view import view_config from pyramid.response import Response - @view_config(name='edit') + @view_config(route_name='edit') def edit(request): return Response('edited!') @@ -514,7 +514,7 @@ against a class as when they are applied against a function. For example: from pyramid.response import Response from pyramid.view import view_config - @view_config() + @view_config(route_name='hello') class MyView(object): def __init__(self, request): self.request = request @@ -539,7 +539,7 @@ decorator syntactic sugar, if you wish: def __call__(self): return Response('hello') - my_view = view_config()(MyView) + my_view = view_config(route_name='hello')(MyView) More than one :class:`~pyramid.view.view_config` decorator can be stacked on top of any number of others. Each decorator creates a separate view @@ -551,8 +551,8 @@ registration. For example: from pyramid.view import view_config from pyramid.response import Response - @view_config(name='edit') - @view_config(name='change') + @view_config(route_name='edit') + @view_config(route_name='change') def edit(request): return Response('edited!') @@ -570,7 +570,7 @@ The decorator can also be used against a method of a class: def __init__(self, request): self.request = request - @view_config(name='hello') + @view_config(route_name='hello') def amethod(self): return Response('hello') @@ -592,7 +592,7 @@ against the ``amethod`` method could be spelled equivalently as the below: from pyramid.response import Response from pyramid.view import view_config - @view_config(attr='amethod', name='hello') + @view_config(attr='amethod', route_name='hello') class MyView(object): def __init__(self, request): self.request = request @@ -624,7 +624,7 @@ this method are very similar to the arguments that you provide to the # config is assumed to be an instance of the # pyramid.config.Configurator class - config.add_view(hello_world, name='hello.html') + config.add_view(hello_world, route_name='hello') The first argument, ``view``, is required. It must either be a Python object which is the view itself or a :term:`dotted Python name` to such an object. @@ -637,102 +637,6 @@ configurations, you don't need to issue a :term:`scan` in order for the view configuration to take effect. .. index:: - single: resource interfaces - -.. _using_resource_interfaces: - -Using Resource Interfaces In View Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Instead of registering your views with a ``context`` that names a Python -resource *class*, you can optionally register a view callable with a -``context`` which is an :term:`interface`. An interface can be attached -arbitrarily to any resource object. View lookup treats context interfaces -specially, and therefore the identity of a resource can be divorced from that -of the class which implements it. As a result, associating a view with an -interface can provide more flexibility for sharing a single view between two -or more different implementations of a resource type. For example, if two -resource objects of different Python class types share the same interface, -you can use the same view configuration to specify both of them as a -``context``. - -In order to make use of interfaces in your application during view dispatch, -you must create an interface and mark up your resource classes or instances -with interface declarations that refer to this interface. - -To attach an interface to a resource *class*, you define the interface and -use the :func:`zope.interface.implements` function to associate the interface -with the class. - -.. code-block:: python - :linenos: - - from zope.interface import Interface - from zope.interface import implements - - class IHello(Interface): - """ A marker interface """ - - class Hello(object): - implements(IHello) - -To attach an interface to a resource *instance*, you define the interface and -use the :func:`zope.interface.alsoProvides` function to associate the -interface with the instance. This function mutates the instance in such a -way that the interface is attached to it. - -.. code-block:: python - :linenos: - - from zope.interface import Interface - from zope.interface import alsoProvides - - class IHello(Interface): - """ A marker interface """ - - class Hello(object): - pass - - def make_hello(): - hello = Hello() - alsoProvides(hello, IHello) - return hello - -Regardless of how you associate an interface, with a resource instance, or a -resource class, the resulting code to associate that interface with a view -callable is the same. Assuming the above code that defines an ``IHello`` -interface lives in the root of your application, and its module is named -"resources.py", the interface declaration below will associate the -``mypackage.views.hello_world`` view with resources that implement, or -provide, this interface. - -.. code-block:: python - :linenos: - - # config is an instance of pyramid.config.Configurator - - config.add_view('mypackage.views.hello_world', name='hello.html', - context='mypackage.resources.IHello') - -Any time a resource that is determined to be the :term:`context` provides -this interface, and a view named ``hello.html`` is looked up against it as -per the URL, the ``mypackage.views.hello_world`` view callable will be -invoked. - -Note, in cases where a view is registered against a resource class, and a -view is also registered against an interface that the resource class -implements, an ambiguity arises. Views registered for the resource class take -precedence over any views registered for any interface the resource class -implements. Thus, if one view configuration names a ``context`` of both the -class type of a resource, and another view configuration names a ``context`` -of interface implemented by the resource's class, and both view -configurations are otherwise identical, the view registered for the context's -class will "win". - -For more information about defining resources with interfaces for use within -view configuration, see :ref:`resources_which_implement_interfaces`. - -.. index:: single: view security pair: security; view @@ -753,8 +657,9 @@ configuration using :meth:`~pyramid.config.Configurator.add_view`: # config is an instance of pyramid.config.Configurator - config.add_view('myproject.views.add_entry', name='add.html', - context='myproject.resources.IBlog', permission='add') + config.add_route('add', '/add.html', factory='mypackage.Blog') + config.add_view('myproject.views.add_entry', route_name='add', + permission='add') When an :term:`authorization policy` is enabled, this view will be protected with the ``add`` permission. The view will *not be called* if the user does @@ -835,7 +740,7 @@ invoked as the result of the ``http_cache`` argument to view configuration. .. index:: pair: view configuration; debugging -ebugging View Configuration +Debugging View Configuration ---------------------------- See :ref:`displaying_matching_views` for information about how to display diff --git a/docs/narr/views.rst b/docs/narr/views.rst index 1c9529860..a3fd61098 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -3,10 +3,10 @@ Views ===== -One of the primary jobs of :app:`Pyramid` is to find and invoke a -:term:`view callable` when a :term:`request` reaches your application. View -callables are bits of code which do something interesting in response to a -request made to your application. +One of the primary jobs of :app:`Pyramid` is to find and invoke a :term:`view +callable` when a :term:`request` reaches your application. View callables +are bits of code which do something interesting in response to a request made +to your application. They are the "meat" of any interesting web application. .. note:: @@ -17,23 +17,10 @@ request made to your application. that implements a view *callable*, and the process of view *lookup*. -The :ref:`urldispatch_chapter`, and :ref:`traversal_chapter` chapters -describes how, using information from the :term:`request`, a -:term:`context` resource is computed. But the context resource itself -isn't very useful without an associated :term:`view callable`. A view -callable returns a response to a user, often using the context resource -to do so. - -The job of actually locating and invoking the "best" :term:`view callable` is -the job of the :term:`view lookup` subsystem. The view lookup subsystem -compares the resource supplied by :term:`resource location` and information -in the :term:`request` against :term:`view configuration` statements made by -the developer to choose the most appropriate view callable for a specific -set of circumstances. - -This chapter describes how view callables work. In the -:ref:`view_config_chapter` chapter, there are details about performing -view configuration, and a detailed explanation of view lookup. +This chapter describes how view callables should be defined. We'll have to +wait until a following chapter (entitled :ref:`view_config_chapter`) to find +out how we actually tell :app:`Pyramid` to wire up view callables to +particular URL patterns and other request circumstances. .. index:: single: view callables @@ -42,26 +29,20 @@ View Callables -------------- View callables are, at the risk of sounding obvious, callable Python -objects. Specifically, view callables can be functions, classes, or -instances that implement an ``__call__`` method (making the -instance callable). +objects. Specifically, view callables can be functions, classes, or instances +that implement an ``__call__`` method (making the instance callable). View callables must, at a minimum, accept a single argument named ``request``. This argument represents a :app:`Pyramid` :term:`Request` -object. A request object encapsulates a WSGI environment provided to -:app:`Pyramid` by the upstream :term:`WSGI` server. As you might expect, -the request object contains everything your application needs to know -about the specific HTTP request being made. +object. A request object represents a :term:`WSGI` environment provided to +:app:`Pyramid` by the upstream WSGI server. As you might expect, the request +object contains everything your application needs to know about the specific +HTTP request being made. A view callable's ultimate responsibility is to create a :mod:`Pyramid` -:term:`Response` object. This can be done by creating the response object in -the view callable code and returning it directly, as we will be doing in this -chapter. However, if a view callable does not return a response itself, it -can be configured to use a :term:`renderer` that converts its return value -into a :term:`Response` object. Using renderers is the common way that -templates are used with view callables to generate markup: see the -:ref:`renderers_chapter` chapter for details. In some cases, a response may -also be generated by raising an exception within a view callable. +:term:`Response` object. This can be done by creating a :term:`Response` +object in the view callable code and returning it directly or by raising +special kinds of exceptions from within the body of a view callable. .. index:: single: view calling convention @@ -160,13 +141,14 @@ the class :class:`pyramid.httpexceptions.HTTPFound` is also a valid response object because it inherits from :class:`~pyramid.response.Response`. For examples, see :ref:`http_exceptions` and :ref:`http_redirect`. -You can also return objects from view callables that aren't instances of (or -instances of classes which are subclasses of) -:class:`pyramid.response.Response` in various circumstances. This can be -helpful when writing tests and when attempting to share code between view -callables. See :ref:`renderers_chapter` for the common way to allow for -this. A much less common way to allow for view callables to return -non-Response objects is documented in :ref:`using_iresponse`. +.. note:: + + You can also return objects from view callables that aren't instances of + :class:`pyramid.response.Response` in various circumstances. This can be + helpful when writing tests and when attempting to share code between view + callables. See :ref:`renderers_chapter` for the common way to allow for + this. A much less common way to allow for view callables to return + non-Response objects is documented in :ref:`using_iresponse`. .. index:: single: view exceptions |
