summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCasey Duncan <casey.duncan@gmail.com>2011-01-02 23:45:33 -0700
committerCasey Duncan <casey.duncan@gmail.com>2011-01-02 23:45:33 -0700
commit8a1b50bc4027e25d5450cc6968f1f005af9d389f (patch)
tree2e689e6e34f6b2a23021aa886004f4baabce0007
parentbb9a3783046db24b2fda6787c232d4168d256729 (diff)
downloadpyramid-8a1b50bc4027e25d5450cc6968f1f005af9d389f.tar.gz
pyramid-8a1b50bc4027e25d5450cc6968f1f005af9d389f.tar.bz2
pyramid-8a1b50bc4027e25d5450cc6968f1f005af9d389f.zip
Split view chapter, move view config after templates, some reordering in view config
-rw-r--r--docs/glossary.rst13
-rw-r--r--docs/index.rst1
-rw-r--r--docs/latexindex.rst1
-rw-r--r--docs/narr/firstapp.rst2
-rw-r--r--docs/narr/traversal.rst19
-rw-r--r--docs/narr/urldispatch.rst7
-rw-r--r--docs/narr/viewconfig.rst965
-rw-r--r--docs/narr/views.rst1116
8 files changed, 1007 insertions, 1117 deletions
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 49d273197..7090b5f93 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -114,12 +114,13 @@ Glossary
view configuration
View configuration is the act of associating a :term:`view
callable` with configuration information. This configuration
- information helps map a given :term:`request` to a particular view
- callable and it can influence the response of a view callable.
- :app:`Pyramid` views can be configured via :term:`imperative
- configuration`, :term:`ZCML` or by a special ``@view_config``
- decorator coupled with a :term:`scan`. See :ref:`views_chapter`
- for more information about view configuration.
+ information helps map a given :term:`request` to a particular view
+ callable and it can influence the response of a view callable.
+ :app:`Pyramid` views can be configured via :term:`imperative
+ configuration`, :term:`ZCML` or by a special ``@view_config``
+ decorator coupled with a :term:`scan`. See
+ :ref:`view_config_chapter` for more information about view
+ configuration.
view name
The "URL name" of a view, e.g ``index.html``. If a view is
diff --git a/docs/index.rst b/docs/index.rst
index 2f3589499..fe3cf2ce8 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -44,6 +44,7 @@ Narrative documentation in chapter form explaining how to use
narr/views
narr/renderers
narr/templates
+ narr/viewconfig
narr/resources
narr/assets
narr/webob
diff --git a/docs/latexindex.rst b/docs/latexindex.rst
index 9635e6e8a..608a49678 100644
--- a/docs/latexindex.rst
+++ b/docs/latexindex.rst
@@ -37,6 +37,7 @@ Narrative Documentation
narr/views
narr/renderers
narr/templates
+ narr/viewconfig
narr/resources
narr/assets
narr/webob
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index 1a81134f5..3f1098da4 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -323,7 +323,7 @@ For more information about the API of a :term:`Configurator` object,
see :class:`pyramid.config.Configurator` .
For more information about :term:`view configuration`, see
-:ref:`views_chapter`.
+:ref:`view_config_chapter`.
An example of using *declarative* configuration (:term:`ZCML`) instead of
imperative configuration to create a similar "hello world" is available
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index 0b0bb1d3e..7c6280ba1 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -83,7 +83,7 @@ name` is the empty string (`''`).
The combination of the context resource and the :term:`view name` found
via traversal is used later in the same request by the :term:`view
lookup` subsystem to find a :term:`view callable`. How :app:`Pyramid`
-performs view lookup is explained within the :ref:`views_chapter`
+performs view lookup is explained within the :ref:`view_config_chapter`
chapter.
.. index::
@@ -217,13 +217,14 @@ We'll provide a description of the algorithm, a diagram of how the algorithm
works, and some example traversal scenarios that might help you understand
how the algorithm operates against a specific resource tree.
-We'll also talk a bit about :term:`view lookup`. The :ref:`views_chapter`
-chapter discusses :term:`view lookup` in detail, and it is the canonical
-source for information about views. Technically, :term:`view lookup` is a
-:app:`Pyramid` subsystem that is separated from traversal entirely. However,
-we'll describe the fundamental behavior of view lookup in the examples in the
-next few sections to give you an idea of how traversal and view lookup
-cooperate, because they are almost always used together.
+We'll also talk a bit about :term:`view lookup`. The
+:ref:`view_config_chapter` chapter discusses :term:`view lookup` in
+detail, and it is the canonical source for information about views.
+Technically, :term:`view lookup` is a :app:`Pyramid` subsystem that is
+separated from traversal entirely. However, we'll describe the
+fundamental behavior of view lookup in the examples in the next few
+sections to give you an idea of how traversal and view lookup cooperate,
+because they are almost always used together.
.. index::
single: view name
@@ -461,7 +462,7 @@ References
A tutorial showing how :term:`traversal` can be used within a :app:`Pyramid`
application exists in :ref:`bfg_wiki_tutorial`.
-See the :ref:`views_chapter` chapter for detailed information about
+See the :ref:`view_config_chapter` chapter for detailed information about
:term:`view lookup`.
The :mod:`pyramid.traversal` module contains API functions that deal with
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index c0b132a04..e64513a96 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -26,7 +26,7 @@ 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:`views_chapter` chapter describes
+:term:`resource location`. The :ref:`view_config_chapter` chapter describes
the details of :term:`view lookup`.
High-Level Operational Overview
@@ -95,7 +95,7 @@ Route Configuration That Names a View Callable
When a route configuration declaration names a ``view`` attribute, the value
of the attribute will reference a :term:`view callable`. This view callable
will be invoked when the route matches. A view callable, as described in
-:ref:`views_chapter`, is developer-supplied code that "does stuff" as the
+:ref:`view_chapter`, is developer-supplied code that "does stuff" as the
result of a request. For more information about how to create view
callables, see :ref:`views_chapter`.
@@ -865,7 +865,8 @@ The ``mypackage.views`` module referred to above might look like so:
The view has access to the matchdict directly via the request, and can access
variables within it that match keys present as a result of the route pattern.
-See :ref:`views_chapter` for more information about views.
+See :ref:`views_chapter`, and :ref:`view_config_chapter` for more
+information about views.
Example 2
~~~~~~~~~
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.
+
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index 08ae5d5d8..48bb7f829 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -31,9 +31,9 @@ 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 provides documentation detailing the process of creating
-view callables, documentation about performing view configuration, and
-a detailed explanation of view lookup.
+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.
View Callables
--------------
@@ -51,13 +51,14 @@ 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 in
-the view callable code and returning it directly. 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.
+: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.
.. index::
single: view calling convention
@@ -66,7 +67,7 @@ templates are used with view callables to generate markup. See the
.. _function_as_view:
Defining a View Callable as a Function
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------------------------
One of the easiest way to define a view callable is to create a function that
accepts a single argument named ``request``, and which returns a
@@ -88,7 +89,7 @@ implemented as a function:
.. _class_as_view:
Defining a View Callable as a Class
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------------
A view callable may also be represented by a Python class instead of a
function. When a view callable is a class, the calling semantics are
@@ -138,7 +139,7 @@ method expected to return a response, you can either:
.. _request_and_context_view_definitions:
Alternate View Callable Argument/Calling Conventions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+----------------------------------------------------
Usually, view callables are defined to accept only a single argument:
``request``. However, view callables may alternately be defined as classes,
@@ -213,7 +214,7 @@ access to the context via ``request.context``.
.. _the_response:
View Callable Responses
-~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------
A view callable may always return an object that implements the :app:`Pyramid`
:term:`Response` interface. The easiest way to return something that
@@ -259,7 +260,7 @@ These attributes form the notional "Pyramid Response interface".
.. _http_redirect:
Using a View Callable to Do an HTTP Redirect
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--------------------------------------------
You can issue an HTTP redirect from within a view by returning a particular
kind of response.
@@ -298,7 +299,7 @@ Unauthorized``.
.. _special_exceptions_in_callables:
Using Special Exceptions In View Callables
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+------------------------------------------
Usually when a Python exception is raised within a view callable,
:app:`Pyramid` allows the exception to propagate all the way out to the
@@ -328,7 +329,7 @@ available to the view which :app:`Pyramid` invokes as
.. _exception_views:
Exception Views
-~~~~~~~~~~~~~~~~
+---------------
The machinery which allows the special :exc:`pyramid.exceptions.NotFound` and
:exc:`pyramid.exceptions.Forbidden` exceptions to be caught by specialized
@@ -412,1084 +413,3 @@ Exception views can be configured with any view registration mechanism:
single: forms, views, and unicode
single: views, forms, and unicode
-Handling Form Submissions in View Callables (Unicode and Character Set Issues)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Most web applications need to accept form submissions from web browsers and
-various other clients. In :app:`Pyramid`, form submission handling logic is
-always part of a :term:`view`. For a general overview of how to handle form
-submission data using the :term:`WebOb` API, see :ref:`webob_chapter` and
-`"Query and POST variables" within the WebOb documentation
-<http://pythonpaste.org/webob/reference.html#query-post-variables>`_.
-:app:`Pyramid` defers to WebOb for its request and response implementations,
-and handling form submission data is a property of the request
-implementation. Understanding WebOb's request API is the key to
-understanding how to process form submission data.
-
-There are some defaults that you need to be aware of when trying to handle
-form submission data in a :app:`Pyramid` view. Having high-order (i.e.,
-non-ASCII) characters in data contained within form submissions is
-exceedingly common, and the UTF-8 encoding is the most common encoding used
-on the web for character data. Since Unicode values are much saner than
-working with and storing bytestrings, :app:`Pyramid` configures the
-:term:`WebOb` request machinery to attempt to decode form submission values
-into Unicode from UTF-8 implicitly. This implicit decoding happens when view
-code obtains form field values via the ``request.params``, ``request.GET``,
-or ``request.POST`` APIs (see :ref:`request_module` for details about these
-APIs).
-
-.. note::
-
- Many people find the difference between Unicode and UTF-8 confusing.
- Unicode is a standard for representing text that supports most of the
- world's writing systems. However, there are many ways that Unicode data
- can be encoded into bytes for transit and storage. UTF-8 is a specific
- encoding for Unicode, that is backwards-compatible with ASCII. This makes
- UTF-8 very convenient for encoding data where a large subset of that data
- is ASCII characters, which is largely true on the web. UTF-8 is also the
- standard character encoding for URLs.
-
-As an example, let's assume that the following form page is served up to a
-browser client, and its ``action`` points at some :app:`Pyramid` view code:
-
-.. code-block:: xml
- :linenos:
-
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
- </head>
- <form method="POST" action="myview">
- <div>
- <input type="text" name="firstname"/>
- </div>
- <div>
- <input type="text" name="lastname"/>
- </div>
- <input type="submit" value="Submit"/>
- </form>
- </html>
-
-The ``myview`` view code in the :app:`Pyramid` application *must* expect that
-the values returned by ``request.params`` will be of type ``unicode``, as
-opposed to type ``str``. The following will work to accept a form post from
-the above form:
-
-.. code-block:: python
- :linenos:
-
- def myview(request):
- firstname = request.params['firstname']
- lastname = request.params['lastname']
-
-But the following ``myview`` view code *may not* work, as it tries to decode
-already-decoded (``unicode``) values obtained from ``request.params``:
-
-.. code-block:: python
- :linenos:
-
- def myview(request):
- # the .decode('utf-8') will break below if there are any high-order
- # characters in the firstname or lastname
- firstname = request.params['firstname'].decode('utf-8')
- lastname = request.params['lastname'].decode('utf-8')
-
-For implicit decoding to work reliably, you should ensure that every form you
-render that posts to a :app:`Pyramid` view explicitly defines a charset
-encoding of UTF-8. This can be done via a response that has a
-``;charset=UTF-8`` in its ``Content-Type`` header; or, as in the form above,
-with a ``meta http-equiv`` tag that implies that the charset is UTF-8 within
-the HTML ``head`` of the page containing the form. This must be done
-explicitly because all known browser clients assume that they should encode
-form data in the same character set implied by ``Content-Type`` value of the
-response containing the form when subsequently submitting that form. There is
-no other generally accepted way to tell browser clients which charset to use
-to encode form data. If you do not specify an encoding explicitly, the
-browser client will choose to encode form data in its default character set
-before submitting it, which may not be UTF-8 as the server expects. If a
-request containing form data encoded in a non-UTF8 charset is handled by your
-view code, eventually the request code accessed within your view will throw
-an error when it can't decode some high-order character encoded in another
-character set within form data, e.g., when ``request.params['somename']`` is
-accessed.
-
-If you are using the :class:`pyramid.response.Response` class to generate a
-response, or if you use the ``render_template_*`` templating APIs, the UTF-8
-charset is set automatically as the default via the ``Content-Type`` header.
-If you return a ``Content-Type`` header without an explicit charset, a
-request will add a ``;charset=utf-8`` trailer to the ``Content-Type`` header
-value for you, for response content types that are textual
-(e.g. ``text/html``, ``application/xml``, etc) as it is rendered. If you are
-using your own response object, you will need to ensure you do this yourself.
-
-.. note:: Only the *values* of request params obtained via
- ``request.params``, ``request.GET`` or ``request.POST`` are decoded
- to Unicode objects implicitly in the :app:`Pyramid` default
- configuration. The keys are still (byte) strings.
-
-.. index::
- single: view configuration
-
-.. _view_configuration:
-
-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
-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.
-
-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: 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.
-
-Predicate attributes of view configuration 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.
-
-For any given request, 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) view 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.
-
-.. 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.
-
-Further Information
--------------------
-
-The chapter entitled :ref:`renderers_chapter` explains how to create
-functions (or instances/classes) which do not return a :term:`Response`
-object, yet which still can be used as view callables.
-