diff options
| author | Chris McDonough <chrism@plope.com> | 2010-12-19 18:40:05 -0500 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2010-12-19 18:40:05 -0500 |
| commit | 53f1bb24eb51ac994185f2365930220a9d87e77e (patch) | |
| tree | 369fa30db6e75f67e3204038196f8515097393f7 /docs/narr/views.rst | |
| parent | a59c789b2bb4a1de5f79537cc2f1022c97bb51f6 (diff) | |
| download | pyramid-53f1bb24eb51ac994185f2365930220a9d87e77e.tar.gz pyramid-53f1bb24eb51ac994185f2365930220a9d87e77e.tar.bz2 pyramid-53f1bb24eb51ac994185f2365930220a9d87e77e.zip | |
merge handlers chapter into views chapter
Diffstat (limited to 'docs/narr/views.rst')
| -rw-r--r-- | docs/narr/views.rst | 262 |
1 files changed, 252 insertions, 10 deletions
diff --git a/docs/narr/views.rst b/docs/narr/views.rst index c66da636f..447385458 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -198,6 +198,58 @@ related view callables. No matter which view calling convention is used, the view code always has access to the context via ``request.context``. +Defining a Set of View Callables Using a Handler +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Along with normal view callable functions, instances, and classes, +:app:`Pyramid` provides the special concept of a :term:`view handler`. View +handlers are a convenience for :term:`URL dispatch` users. The concept of a +view handler is analogous to a "controller" in Pylons 1.0. Using a view +handler instead of a plain function or class :term:`view callable` makes it +unnecessary to call :meth:`pyramid.config.Configurator.add_route` (and/or +:meth:`pyramid.config.Configurator.add_view`) "by hand" multiple times, +making it more pleasant to register a collection of views as a single class +when using :term:`url dispatch`. The view handler machinery also introduces +the concept of an ``action``, which is used as a :term:`view predicate` to +control which method of the handler is called. + +.. note:: + + View handlers are *not* useful when using :term:`traversal`, only when using + :term:`url dispatch`. + +The view handler class is initialized by :app:`Pyramid` in the same manner as +a view *class*. Its ``__init__`` is called with a request object (see +:ref:`class_as_view`) as its argument when a request enters the system which +corresponds with a view handler registration made during configuration. +After the view handler class is instantiated, a method on the instance is +called. Typically, each method of the handler is used as a view callable. +The methods which are called depends on the view handler's configuration. + +Here's an example view handler class: + +.. code-block:: python + :linenos: + + from pyramid.response import Response + + from pyramid.view import action + + class Hello(object): + def __init__(self, request): + self.request = request + + def index(self): + return Response('Hello world!') + + @action(renderer="mytemplate.mak") + def bye(self): + return {} + +Handlers are added to application configuration via the +:meth:`pyramid.config.Configurator.add_handler` API, as described in +:ref:`using_add_handler`. + .. index:: single: view response single: response @@ -524,8 +576,8 @@ using your own response object, you will need to ensure you do this yourself. .. _view_configuration: -View Configuration: Mapping a Resource Type to a View ------------------------------------------------------ +View Configuration: Mapping a Resource or URL Pattern to a View Callable +------------------------------------------------------------------------ A developer makes a :term:`view callable` available for use within a :app:`Pyramid` application via :term:`view configuration`. A view @@ -547,16 +599,21 @@ View configuration is performed in one of these ways: :meth:`pyramid.config.Configurator.add_view` and :ref:`mapping_views_using_imperative_config_section`. -Both of these mechanisms is completely equivalent to the other. +- By specifying a view within a :term:`route configuration`. View + configuration via a route configuration is performed by using the + :meth:`pyramid.config.Configurator.add_route` method, passing a ``view`` + argument specifying a view callable. -.. note:: You can also add view configuration by adding a ``<view>`` - declaration to :term:`ZCML` used by your application as per - :ref:`mapping_views_using_zcml_section` and :ref:`view_directive`. +- by using the :meth:`pyramid.config.Configurator.add_handler` against a + :term:`view handler` class (useful only for :term:`URL dispatch` + applications). -A view configuration might also be performed by virtue of :term:`route -configuration`. View configuration via route configuration is performed by -using the :meth:`pyramid.config.Configurator.add_route` method to create a -route with a ``view`` argument. +.. note:: You can also add view configuration by adding a ``<view>`` or + ``<handler>`` declaration to :term:`ZCML` used by your application as per + :ref:`mapping_views_using_zcml_section`, :ref:`view_directive`, and + :ref:`handler_directive`. + +A view configuration might also be performed by virtue of .. note:: ZCML users can use :ref:`route_directive` to perform the same task. See also :ref:`zcml_route_configuration`. @@ -1055,6 +1112,191 @@ which is the view itself or a :term:`dotted Python name` to such an object. All other arguments are optional. See :meth:`pyramid.config.Configurator.add_view` for more information. +.. _using_add_handler: + +Using :meth:`~pyramid.config.Configurator.add_handler` to Register a Handler +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :meth:`pyramid.config.Configurator.add_handler` method will scan a +:term:`view handler` class and automatically set up view configurations for +its methods that represent "auto-exposed" view callable, or those that were +decorated explicitly with the :class:`~pyramid.view.action` decorator. This +decorator is used to setup additional view configuration information for +individual methods of the class, and can be used repeatedly for a single view +method to register multiple view configurations for it. + +.. code-block:: python + :linenos: + + from myapp.handlers import Hello + config.add_handler('hello', '/hello/{action}', handler=Hello) + +This example will result in a route being added for the pattern +``/hello/{action}``, each method of the ``Hello`` class will then be examined +to register the views. The value of ``{action}`` in the route pattern will be +used to determine which view should be called, and each view in the class +will be setup with a view predicate that requires a specific ``action`` name. + +If the URL in the above example was ``/hello/index``, then the ``index`` +method of the Hello class would be called. + +Alternatively, the action can be declared specifically for a URL to go to a +specific ``action`` name: + +.. code-block:: python + :linenos: + + from myapp.handlers import Hello + config.add_handler('hello_index', '/hello/index', + handler=Hello, action='index') + +This will result one of the methods that are configured for the ``action`` of +'index' in the ``Hello`` handler class to be called. In this case the name of +the method is the same as the action name: 'index'. However, this need not be +the case, as we will see below. + +When calling :meth:`~pyramid.config.Configurator.add_handler`, an ``action`` +is required in either the route pattern or as a keyword argument, but +**cannot appear in both places**. A ``handler`` argument must also be +supplied, which can be either a :term:`asset specification` or a Python +reference to the handler class. Additional keyword arguments are passed +directly through to :meth:`pyramid.config.Configurator.add_route`. + +For example: + +.. code-block:: python + :linenos: + + config.add_handler('hello', '/hello/{action}', + handler='mypackage.handlers.MyHandler') + +Multiple :meth:`~pyramid.config.Configurator.add_handler` calls can specify +the same handler, to register specific route names for different +handler/action combinations. For example: + +.. code-block:: python + :linenos: + + config.add_handler('hello_index', '/hello/index', + handler=Hello, action='index') + config.add_handler('bye_index', '/hello/bye', + handler=Hello, action='bye') + +.. note:: + + Handler configuration may also be added to the system via :term:`ZCML` (see + :ref:`zcml_handler_configuration`). + +View Setup in the Handler Class ++++++++++++++++++++++++++++++++ + +The handler class specified can have a single class level attribute called +``__autoexpose__`` which should be a regular expression or the value +``None``. It's used to determine which method names will result in additional +view configurations being registered. + +When :meth:`~pyramid.config.Configurator.add_handler` runs, every +method in the handler class will be searched and a view registered if the +method name matches the ``__autoexpose__`` regular expression, or if the +method was decorated with :class:`~pyramid.view.action`. + +Every method in the handler class that has a name meeting the +``_autoexpose__`` regular expression will have a view registered for an +``action`` name corresponding to the method name. This functionality can be +disabled by setting the ``__autoexpose__`` attribute to ``None``: + +.. code-block:: python + :linenos: + + from pyramid.view import action + + class Hello(object): + __autoexpose__ = None + + def __init__(self, request): + self.request = request + + @action() + def index(self): + return Response('Hello world!') + + @action(renderer="mytemplate.mak") + def bye(self): + return {} + +With auto-expose effectively disabled, no views will be registered for a +method unless it is specifically decorated with :class:`~pyramid.view.action`. + +Action Decorators in a Handler +++++++++++++++++++++++++++++++ + +The :class:`~pyramid.view.action` decorator registers view configuration +information on the handler method, which is used by +:meth:`~pyramid.config.Configurator.add_handler` to setup the view +configuration. + +All keyword arguments are recorded, and passed to +:meth:`~pyramid.config.Configurator.add_view`. Any valid keyword arguments +for :meth:`~pyramid.config.Configurator.add_view` can thus be used with the +:class:`~pyramid.view.action` decorator to further restrict when the view +will be called. + +One important difference is that a handler method can respond to an +``action`` name that is different from the method name by passing in a +``name`` argument. + +Example: + +.. code-block:: python + :linenos: + + from pyramid.view import action + + class Hello(object): + def __init__(self, request): + self.request = request + + @action(name='index', renderer='created.mak', request_method='POST') + def create(self): + return {} + + @action(renderer="view_all.mak", request_method='GET') + def index(self): + return {} + +This will register two views that require the ``action`` to be ``index``, +with the additional view predicate requiring a specific request method. + +It can be useful to decorate a single method multiple times with +:class:`~pyramid.view.action`. Each action decorator will register a new view +for the method. By specifying different names and renderers for each action, +the same view logic can be exposed and rendered differently on multiple URLs. + +Example: + +.. code-block:: python + :linenos: + + from pyramid.view import action + + class Hello(object): + def __init__(self, request): + self.request = request + + @action(name='home', renderer='home.mak') + @action(name='about', renderer='about.mak') + def show_template(self): + # prep some template vars + return {} + + # in the config + config.add_handler('hello', '/hello/{action}', handler=Hello) + +With this configuration, the url ``/hello/home`` will find a view +configuration that results in calling the ``show_template`` method, then +rendering the template with ``home.mak``, and the url ``/hello/about`` will +call the same method and render the ``about.mak`` template. + .. index:: single: resource interfaces |
