summaryrefslogtreecommitdiff
path: root/docs/narr/viewconfig.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/narr/viewconfig.rst')
-rw-r--r--docs/narr/viewconfig.rst965
1 files changed, 965 insertions, 0 deletions
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
new file mode 100644
index 000000000..39c0a0d1f
--- /dev/null
+++ b/docs/narr/viewconfig.rst
@@ -0,0 +1,965 @@
+.. _view_config_chapter:
+
+.. _view_configuration:
+
+View Configuration
+==================
+
+.. index::
+ single: view lookup
+
+.. _view_lookup:
+
+View Lookup and Invocation
+--------------------------
+
+:term:`View lookup` is the :app:`Pyramid` subsystem responsible for finding
+an invoking a :term:`view callable`. The view lookup subsystem is passed a
+:term:`context` and a :term:`request` object.
+
+:term:`View configuration` information stored within in the
+:term:`application registry` is compared against the context and request by
+the view lookup subsystem in order to find the "best" view callable for the
+set of circumstances implied by the context and request.
+
+:term:`View predicate` attributes are an important part of view
+configuration that enables the :term:`View lookup` subsystem to find and
+invoke the appropriate view. Predicate attributes can be thought of
+like "narrowers". In general, the greater number of predicate
+attributes possessed by a view's configuration, the more specific the
+circumstances need to be before the registered view callable will be
+invoked.
+
+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
+configuration associates a view callable with a set of statements that
+determine the set of circumstances which must be true for the view callable
+to be invoked.
+
+A view configuration statement is made about information present in the
+:term:`context` resource and the :term:`request`.
+
+View configuration is performed in one of these ways:
+
+- by running a :term:`scan` against application source code which has a
+ :class:`pyramid.view.view_config` decorator attached to a Python object as
+ per :class:`pyramid.view.view_config` and
+ :ref:`mapping_views_using_a_decorator_section`.
+
+- by using the :meth:`pyramid.config.Configurator.add_view` method as per
+ :meth:`pyramid.config.Configurator.add_view` and
+ :ref:`mapping_views_using_imperative_config_section`.
+
+- 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.
+
+- by using the :meth:`pyramid.config.Configurator.add_handler` against a
+ :term:`view handler` class (useful only for :term:`URL dispatch`
+ applications).
+
+.. note:: You can also add view configuration by adding a ``<view>``,
+ ``<route>`` or ``<handler>`` declaration to :term:`ZCML` used by your
+ application as per :ref:`mapping_views_using_zcml_section`,
+ :ref:`view_directive`, :ref:`route_directive` or :ref:`handler_directive`.
+
+.. _view_configuration_parameters:
+
+View Configuration Parameters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All forms of view configuration accept the same general types of arguments.
+
+Many arguments supplied during view configuration are :term:`view predicate`
+arguments. View predicate arguments used during view configuration are used
+to narrow the set of circumstances in which :mod:`view lookup` will find a
+particular view callable.
+
+In general, the fewer number of predicates which are supplied to a
+particular view configuration, the more likely it is that the associated
+view callable will be invoked. The greater the number supplied, the
+less likely. A view with five predicates will always be found and
+evaluated before a view with two, for example. All predicates must
+match for the associated view to be called.
+
+This does not mean however, that :app:`Pyramid` "stops looking" when it
+finds a view registration with predicates that don't match. If one set
+of view predicates does not match, the "next most specific" view (if
+any) is consulted for predicates, and so on, until a view is found, or
+no view can be matched up with the request. The first view with a set
+of predicates all of which match the request environment will be
+invoked.
+
+If no view can be found with predicates which allow it to be matched up with
+the request, :app:`Pyramid` will return an error to the user's browser,
+representing a "not found" (404) page. See :ref:`changing_the_notfound_view`
+for more information about changing the default notfound view.
+
+Some view configuration arguments are non-predicate arguments. These tend to
+modify the response of the view callable or prevent the view callable from
+being invoked due to an authorization policy. The presence of non-predicate
+arguments in a view configuration does not narrow the circumstances in which
+the view callable will be invoked.
+
+Non-Predicate Arguments
++++++++++++++++++++++++
+
+``permission``
+ The name of a :term:`permission` that the user must possess in order to
+ invoke the :term:`view callable`. See :ref:`view_security_section` for
+ more information about view security and permissions.
+
+ If ``permission`` is not supplied, no permission is registered for this
+ view (it's accessible by any caller).
+
+``attr``
+ The view machinery defaults to using the ``__call__`` method of the
+ :term:`view callable` (or the function itself, if the view callable is a
+ function) to obtain a response. 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 ``attr`` is not supplied, ``None`` is used (implying the function itself
+ if the view is a function, or the ``__call__`` callable attribute if the
+ view is a class).
+
+``renderer``
+ Denotes the :term:`renderer` implementation which will be used to construct
+ a :term:`response` from the associated view callable's return value. (see
+ also :ref:`renderers_chapter`).
+
+ 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``) naming a
+ :term:`renderer` implementation. If the ``renderer`` value does not
+ contain a dot (``.``), the specified string 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`` value
+ 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.
+
+ When the renderer is a path, although a path is usually just a simple
+ relative pathname (e.g. ``templates/foo.pt``, implying that a template
+ named "foo.pt" is in the "templates" directory relative to the directory of
+ the current :term:`package`), a path can be absolute, starting with a slash
+ on UNIX or a drive letter prefix on Windows. The path can alternately be a
+ :term:`asset specification` in the form
+ ``some.dotted.package_name:relative/path``, making it possible to address
+ template assets which live in a separate package.
+
+ The ``renderer`` attribute is optional. If it is not defined, the "null"
+ renderer is assumed (no rendering is performed and the value is passed back
+ to the upstream :app:`Pyramid` machinery unmolested). Note that if the
+ view callable itself returns a :term:`response` (see :ref:`the_response`),
+ the specified renderer implementation is never called.
+
+``wrapper``
+ The :term:`view name` of a different :term:`view configuration` which will
+ receive the response body of this view as the ``request.wrapped_body``
+ attribute of its own :term:`request`, and the :term:`response` returned by
+ this view as the ``request.wrapped_response`` attribute of its own request.
+ Using a wrapper makes it possible to "chain" views together to form a
+ composite response. The response of the outermost wrapper view will be
+ returned to the user. The wrapper view will be found as any view is found:
+ see :ref:`view_lookup`. The "best" wrapper view will be found based on the
+ lookup ordering: "under the hood" this wrapper view is looked up via
+ ``pyramid.view.render_view_to_response(context, request,
+ 'wrapper_viewname')``. The context and request of a wrapper view is the
+ same context and request of the inner view.
+
+ If ``wrapper`` is not supplied, no wrapper view is used.
+
+Predicate Arguments
++++++++++++++++++++
+
+These arguments modify view lookup behavior. In general, the more predicate
+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.
+
+ If ``name`` is not supplied, the empty string is used (implying the default
+ view).
+
+``context``
+ An object representing a Python class that the :term:`context` resource
+ must be an instance of *or* the :term:`interface` that the :term:`context`
+ resource must provide in order for this view to be found and called. This
+ predicate is true when the :term:`context` resource is an instance of the
+ represented class or if the :term:`context` resource provides the
+ represented interface; it is otherwise false.
+
+ If ``context`` is not supplied, the value ``None``, which matches any
+ resource, is used.
+
+``route_name``
+ If ``route_name`` is supplied, the view callable will be invoked only when
+ the named route has matched.
+
+ This value must match the ``name`` of a :term:`route configuration`
+ declaration (see :ref:`urldispatch_chapter`) that must match before this
+ view will be called. Note that the ``route`` configuration referred to by
+ ``route_name`` will usually have a ``*traverse`` token in the value of its
+ ``pattern``, representing a part of the path that will be used by
+ :term:`traversal` against the result of the route's :term:`root factory`.
+
+ If ``route_name`` is not supplied, the view callable will be have a chance
+ of being invoked if no other route was matched. This is when the
+ request/context pair found via :term:`resource location` does not indicate
+ it matched any configured route.
+
+``request_type``
+ This value should be an :term:`interface` that the :term:`request` must
+ provide in order for this view to be found and called.
+
+ If ``request_type`` is not supplied, the value ``None`` is used, implying
+ any request type.
+
+ *This is an advanced feature, not often used by "civilians"*.
+
+``request_method``
+ This value can either be one of the strings ``GET``, ``POST``, ``PUT``,
+ ``DELETE``, or ``HEAD`` representing an HTTP ``REQUEST_METHOD``. A view
+ declaration with this argument ensures that the view will only be called
+ when the request's ``method`` attribute (aka the ``REQUEST_METHOD`` of the
+ WSGI environment) string matches the supplied value.
+
+ If ``request_method`` is not supplied, the view will be invoked regardless
+ of the ``REQUEST_METHOD`` of the :term:`WSGI` environment.
+
+``request_param``
+ This value can be any string. A view declaration with this argument
+ ensures that the view will only be called when the :term:`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 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 view to "match" the current
+ request.
+
+ If ``request_param`` is not supplied, the view will be invoked without
+ consideration of keys and values in the ``request.params`` dictionary.
+
+``containment``
+ This value should be a reference to a Python class or :term:`interface`
+ that a parent object in the context resource's :term:`lineage` must provide
+ in order for this view to be found and called. The resources in your
+ resource tree must be "location-aware" to use this feature.
+
+ If ``containment`` is not supplied, the interfaces and classes in the
+ lineage are not considered when deciding whether or not to invoke the view
+ callable.
+
+ See :ref:`location_aware` for more information about location-awareness.
+
+``xhr``
+ This value should be either ``True`` or ``False``. If this value is
+ specified and is ``True``, the :term:`WSGI` environment must possess an
+ ``HTTP_X_REQUESTED_WITH`` (aka ``X-Requested-With``) header that has the
+ value ``XMLHttpRequest`` for the associated view callable to be found and
+ called. This is useful for detecting AJAX requests issued from jQuery,
+ Prototype and other Javascript libraries.
+
+ If ``xhr`` is not specified, the ``HTTP_X_REQUESTED_WITH`` HTTP header is
+ not taken into consideration when deciding whether or not to invoke the
+ associated view callable.
+
+``accept``
+ The value of this argument 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 ``accept`` is not specified, the ``HTTP_ACCEPT`` HTTP header is not
+ taken into consideration when deciding whether or not to invoke the
+ associated view callable.
+
+``header``
+ This value represents an HTTP header name or a header name/value pair.
+
+ If ``header`` is specified, it must be a header name or a
+ ``headername:headervalue`` pair.
+
+ If ``header`` is specified without a value (a bare header name only,
+ e.g. ``If-Modified-Since``), the view will only be invoked if the HTTP
+ header exists with any value in the request.
+
+ If ``header`` is specified, and possesses a name/value pair
+ (e.g. ``User-Agent:Mozilla/.*``), the view will only be invoked if the HTTP
+ header exists *and* the HTTP header matches the value requested. When the
+ ``headervalue`` contains a ``:`` (colon), it will be considered a
+ name/value pair (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``).
+ The value portion should be a regular expression.
+
+ 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 ``header`` is not specified, the composition, presence or absence of
+ HTTP headers is not taken into consideration when deciding whether or not
+ to invoke the associated view callable.
+
+``path_info``
+ This value represents a regular expression pattern that will be tested
+ against the ``PATH_INFO`` WSGI environment variable to decide whether or
+ not to call the associated view callable. If the regex matches, this
+ predicate will be ``True``.
+
+ If ``path_info`` is not specified, the WSGI ``PATH_INFO`` is not taken into
+ consideration when deciding whether or not to invoke the associated view
+ callable.
+
+``custom_predicates``
+ If ``custom_predicates`` is specified, it must be a sequence of references
+ to custom predicate callables. Use custom predicates when no set of
+ predefined predicates do 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 view callable will be considered viable for a given request.
+
+ If ``custom_predicates`` is not specified, no custom predicates are
+ used.
+
+.. index::
+ single: view_config decorator
+
+.. _mapping_views_using_a_decorator_section:
+
+View Configuration Using the ``@view_config`` Decorator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For better locality of reference, you may use the
+:class:`pyramid.view.view_config` decorator to associate your view functions
+with URLs instead of using :term:`ZCML` or imperative configuration for the
+same purpose.
+
+.. warning::
+
+ Using this feature tends to slows down application startup slightly, as
+ more work is performed at application startup to scan for view
+ declarations.
+
+Usage of the ``view_config`` decorator is a form of :term:`declarative
+configuration`, like ZCML, but in decorator form.
+:class:`pyramid.view.view_config` can be used to associate :term:`view
+configuration` information -- as done via the equivalent imperative code or
+ZCML -- with a function that acts as a :app:`Pyramid` view callable. All
+arguments to the :meth:`pyramid.config.Configurator.add_view` method (save
+for the ``view`` argument) are available in decorator form and mean precisely
+the same thing.
+
+An example of the :class:`pyramid.view.view_config` decorator might reside in
+a :app:`Pyramid` application module ``views.py``:
+
+.. ignore-next-block
+.. code-block:: python
+ :linenos:
+
+ from resources import MyResource
+ from pyramid.view import view_config
+ from pyramid.response import Response
+
+ @view_config(name='my_view', request_method='POST', context=MyResource,
+ permission='read')
+ def my_view(request):
+ return Response('OK')
+
+Using this decorator as above replaces the need to add this imperative
+configuration stanza:
+
+.. ignore-next-block
+.. code-block:: python
+ :linenos:
+
+ config.add_view('.views.my_view', name='my_view', request_method='POST',
+ context=MyResource, permission='read')
+
+All arguments to ``view_config`` may be omitted. For example:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.response import Response
+ from pyramid.view import view_config
+
+ @view_config()
+ def my_view(request):
+ """ My view """
+ return Response()
+
+Such a registration as the one directly above implies that the view name will
+be ``my_view``, registered with a ``context`` argument that matches any
+resource type, using no permission, registered against requests with any
+request method, request type, request param, route name, or containment.
+
+The mere existence of a ``@view_config`` decorator doesn't suffice to perform
+view configuration. All that the decorator does is "annotate" the function
+with your configuration declarations, it doesn't process them. To make
+:app:`Pyramid` process your :class:`pyramid.view.view_config` declarations,
+you *must* do use the ``scan`` method of a
+:class:`pyramid.config.Configurator`:
+
+.. code-block:: python
+ :linenos:
+
+ # config is assumed to be an instance of the
+ # pyramid.config.Configurator class
+ config.scan()
+
+.. note:: See :ref:`zcml_scanning` for information about how to invoke a scan
+ via ZCML (if you're not using imperative configuration).
+
+Please see :ref:`decorations_and_code_scanning` for detailed information
+about what happens when code is scanned for configuration declarations
+resulting from use of decorators like :class:`pyramid.view.view_config`.
+
+See :ref:`configuration_module` for additional API arguments to the
+:meth:`pyramid.config.Configurator.scan` method. For example, the method
+allows you to supply a ``package`` argument to better control exactly *which*
+code will be scanned.
+
+``@view_config`` Placement
+++++++++++++++++++++++++++
+
+A :class:`pyramid.view.view_config` decorator can be placed in various points
+in your application.
+
+If your view callable is a function, it may be used as a function decorator:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.view import view_config
+ from pyramid.response import Response
+
+ @view_config(name='edit')
+ def edit(request):
+ return Response('edited!')
+
+If your view callable is a class, the decorator can also be used as a class
+decorator in Python 2.6 and better (Python 2.5 and below do not support class
+decorators). All the arguments to the decorator are the same when applied
+against a class as when they are applied against a function. For example:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.response import Response
+ from pyramid.view import view_config
+
+ @view_config()
+ class MyView(object):
+ def __init__(self, request):
+ self.request = request
+
+ def __call__(self):
+ return Response('hello')
+
+You can use the :class:`pyramid.view.view_config` decorator as a simple
+callable to manually decorate classes in Python 2.5 and below without the
+decorator syntactic sugar, if you wish:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.response import Response
+ from pyramid.view import view_config
+
+ class MyView(object):
+ def __init__(self, request):
+ self.request = request
+
+ def __call__(self):
+ return Response('hello')
+
+ my_view = view_config()(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
+registration. For example:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.view import view_config
+ from pyramid.response import Response
+
+ @view_config(name='edit')
+ @view_config(name='change')
+ def edit(request):
+ return Response('edited!')
+
+This registers the same view under two different names.
+
+The decorator can also be used against class methods:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.response import Response
+ from pyramid.view import view_config
+
+ class MyView(object):
+ def __init__(self, request):
+ self.request = request
+
+ @view_config(name='hello')
+ def amethod(self):
+ return Response('hello')
+
+When the decorator is used against a class method, a view is registered for
+the *class*, so the class constructor must accept an argument list in one of
+two forms: either it must accept a single argument ``request`` or it must
+accept two arguments, ``context, request``.
+
+The method which is decorated must return a :term:`response`.
+
+Using the decorator against a particular method of a class is equivalent to
+using the ``attr`` parameter in a decorator attached to the class itself.
+For example, the above registration implied by the decorator being used
+against the ``amethod`` method could be spelled equivalently as the below:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.response import Response
+ from pyramid.view import view_config
+
+ @view_config(attr='amethod', name='hello')
+ class MyView(object):
+ def __init__(self, request):
+ self.request = request
+
+ def amethod(self):
+ return Response('hello')
+
+.. index::
+ single: add_view
+
+.. _mapping_views_using_imperative_config_section:
+
+View Registration Using :meth:`~pyramid.config.Configurator.add_view`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The :meth:`pyramid.config.Configurator.add_view` method within
+:ref:`configuration_module` is used to configure a view imperatively. The
+arguments to this method are very similar to the arguments that you provide
+to the ``@view_config`` decorator. For example:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.response import Response
+
+ def hello_world(request):
+ return Response('hello!')
+
+ # config is assumed to be an instance of the
+ # pyramid.config.Configurator class
+ config.add_view(hello_world, name='hello.html')
+
+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.
+All other arguments are optional. See
+:meth:`pyramid.config.Configurator.add_view` for more information.
+
+.. _using_add_handler:
+
+Handler Registration Using :meth:`~pyramid.config.Configurator.add_handler`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:app:`Pyramid` provides the special concept of a :term:`view handler`. View
+handlers are view classes that implement a number of methods, each of which
+is a :term:`view callable` as a convenience for :term:`URL dispatch` users.
+
+.. note::
+
+ View handlers are *not* useful when using :term:`traversal`, only when using
+ :term:`url dispatch`.
+
+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. The method name is the
+default *action name* of a handler view callable.
+
+The concept of a view handler is analogous to a "controller" in Pylons 1.0.
+
+The view handler class is initialized by :app:`Pyramid` in the same manner as
+a "plain" view class. Its ``__init__`` is called with a request object (see
+:ref:`class_as_view`). It implements methods, each of which is a :term:`view
+callable`. When a request enters the system which corresponds with an
+*action* related to one of its view callable methods, this method is called,
+and it is expected to return a response.
+
+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 {}
+
+The :class:`pyramid.view.action` decorator is used to fine-tune the view
+parameters for each potential view callable which is a method of the handler.
+
+Handlers are added to application configuration via the
+:meth:`pyramid.config.Configurator.add_handler` API. 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}``, and each method of the ``Hello`` class will then be
+examined to see if it should be registered as a potential view callable when
+the ``/hello/{action}`` pattern matches. 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. By default, the action name for a method of a
+handler is the method name.
+
+If the URL was ``/hello/index``, the above example pattern would match, and,
+by default, the ``index`` method of the ``Hello`` class would be called.
+
+Alternatively, the action can be declared specifically for a URL to be
+registered for 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
++++++++++++++++++++++++++++++++
+
+A handler class 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
+
+.. _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
+
+.. _view_security_section:
+
+Configuring View Security
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If an :term:`authorization policy` is active, any :term:`permission` attached
+to a :term:`view configuration` found during view lookup will be verified.
+This will ensure that the currently authenticated user possesses that
+permission against the :term:`context` resource before the view function is
+actually called. Here's an example of specifying a permission in a view
+configuration using :meth:`pyramid.config.Configurator.add_view`:
+
+.. code-block:: python
+ :linenos:
+
+ # config is an instance of pyramid.config.Configurator
+
+ config.add_view('myproject.views.add_entry', name='add.html',
+ context='myproject.resources.IBlog', 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
+not possess the ``add`` permission relative to the current :term:`context`.
+Instead the :term:`forbidden view` result will be returned to the client as
+per :ref:`protecting_views`.
+
+.. index::
+ single: debugging not found errors
+ single: not found error (debugging)
+
+.. _debug_notfound_section:
+
+:exc:`NotFound` Errors
+~~~~~~~~~~~~~~~~~~~~~~
+
+It's useful to be able to debug :exc:`NotFound` error responses when they
+occur unexpectedly due to an application registry misconfiguration. To debug
+these errors, use the ``PYRAMID_DEBUG_NOTFOUND`` environment variable or the
+``debug_notfound`` configuration file setting. Details of why a view was not
+found will be printed to ``stderr``, and the browser representation of the
+error will include the same information. See :ref:`environment_chapter` for
+more information about how, and where to set these values.
+