summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/narr/configuration.rst9
-rw-r--r--docs/narr/contextfinding.rst13
-rw-r--r--docs/narr/firstapp.rst10
-rw-r--r--docs/narr/handlers.rst46
-rw-r--r--docs/narr/hybrid.rst72
-rw-r--r--docs/narr/install.rst1
-rw-r--r--docs/narr/project.rst13
-rw-r--r--docs/narr/static.rst76
-rw-r--r--docs/narr/traversal.rst2
-rw-r--r--docs/narr/urldispatch.rst84
-rw-r--r--docs/narr/views.rst406
-rw-r--r--docs/narr/webob.rst21
12 files changed, 421 insertions, 332 deletions
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst
index 28388ef96..4f26b092a 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -10,9 +10,9 @@ Each deployment of an application written using :app:`Pyramid` implies a
specific *configuration* of the framework itself. For example, an
application which serves up MP3s for user consumption might plug code into
the framework that manages songs, while an application that manages corporate
-data might plug in code that manages accounting information. :app:`Pyramid`
-refers to the way in which code is plugged in to it for a specific
-application as "configuration".
+data might plug in code that manages accounting information. The way in which
+code is plugged in to :app:`Pyramid`, for a specific application, is referred
+to as "configuration".
Most people understand "configuration" as coarse settings that inform the
high-level operation of a specific application deployment. For instance,
@@ -21,8 +21,7 @@ application startup time as "configuration". :app:`Pyramid` extends this
pattern to application development, using the term "configuration" to express
standardized ways that code gets plugged into a deployment of the framework
itself. When you plug code into the :app:`Pyramid` framework, you are
-"configuring" :app:`Pyramid` for the purpose of creating a particular
-application deployment.
+"configuring" :app:`Pyramid` to create a particular application.
.. index::
single: imperative configuration
diff --git a/docs/narr/contextfinding.rst b/docs/narr/contextfinding.rst
index 770f97d15..691ad7b8e 100644
--- a/docs/narr/contextfinding.rst
+++ b/docs/narr/contextfinding.rst
@@ -51,16 +51,15 @@ requesting user.
that do not provide a notion of a context.
There are two separate :term:`context finding` subsystems in
-:app:`Pyramid`: :term:`traversal` and :term:`URL dispatch`. The
-subsystems are documented within this chapter. They can be used
-separately or they can be combined. Three chapters which follow
-describe :term:`context finding`: :ref:`traversal_chapter`,
+:app:`Pyramid`: :term:`traversal` and :term:`URL dispatch`. They can
+be used separately or they can be combined. Three chapters which
+follow describe :term:`context finding`: :ref:`traversal_chapter`,
:ref:`urldispatch_chapter` and :ref:`hybrid_chapter`.
There is only one :term:`view lookup` subsystem present in
-:app:`Pyramid`. Where appropriate, within this chapter, we
-describe how view lookup interacts with context finding. One chapter
-which follows describes :term:`view lookup`: :ref:`views_chapter`.
+:app:`Pyramid`. Where appropriate, we will describe how view lookup
+interacts with context finding. One chapter which follows describes
+:term:`view lookup`: :ref:`views_chapter`.
Should I Use Traversal or URL Dispatch for Context Finding?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index d23a79c4b..b40faee3d 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -137,10 +137,10 @@ passed to the ``Response`` constructor as the *body* of the response. In the
Application Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~
-In the above script, the following code, representing the
-*configuration* of an application which uses the previously defined
-imports and function definitions is placed within the confines of an
-``if`` statement:
+In the above script, the following code represents the *configuration* of this
+simple application. The application is configured using the previously defined
+imports and function definitions, placed within the confines of an ``if``
+statement:
.. code-block:: python
:linenos:
@@ -242,7 +242,7 @@ circumstances which would cause the view configuration's callable to
be invoked. In general, a greater number of predicates supplied along
with a view configuration will more strictly limit the applicability
of its associated view callable. When :app:`Pyramid` processes a
-request, however, the view callable with the *most specific* view
+request, the view callable with the *most specific* view
configuration (the view configuration that matches the most specific
set of predicates) is always invoked.
diff --git a/docs/narr/handlers.rst b/docs/narr/handlers.rst
index 9a5267b2a..f6e658cf0 100644
--- a/docs/narr/handlers.rst
+++ b/docs/narr/handlers.rst
@@ -19,20 +19,21 @@ predicate` to control which method of the handler is called.
:term:`url dispatch`. 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 view class. Its ``__init__`` is called with a request object (see
-:ref:`class_as_view`) when a request enters the system which corresponds with
-a view handler registration made during configuration. A method of the view
-handler class is then called. The method which is called depends on the view
-handler configuration.
-
-The :meth:`pyramid.config.Configurator.add_handler` method will scan
-the handler class and automatically set up views for methods that are
-auto-exposed or were decorated with :class:`~pyramid.view.action`. The
-:class:`~pyramid.view.action` decorator is used to setup additional view
-configuration information for individual class methods, and can be used
-repeatedly for a single method to register multiple view configurations that
-will call that view callable.
+The view handler class is initialized by :app:`Pyramid` in the same
+manner as a view class. Its ``__init__`` is called with a request
+object (see :ref:`class_as_view`) as its argument when a request enters
+the system which corresponds with a view handler registration made
+during configuration. After the view handler class is instantiated, a
+method on the instance is called. The method which is called depends on
+the view handler configuration.
+
+The :meth:`pyramid.config.Configurator.add_handler` method will
+scan the handler class and automatically set up views for methods that
+are auto-exposed, or were decorated 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.
Here's an example view handler class:
@@ -82,9 +83,9 @@ specific ``action`` name:
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. Other methods in the
-handler class not named 'index' might be called if they were configured to be
-called when the ``action`` name is 'index' as will be seen below.
+'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.
.. note::
@@ -175,7 +176,7 @@ Action Decorator
----------------
The :class:`~pyramid.view.action` decorator registers view configuration
-information on the handler method which is used by
+information on the handler method, which is used by
:meth:`~pyramid.config.Configurator.add_handler` to setup the view
configuration.
@@ -210,10 +211,11 @@ Example:
This will register two views that require the ``action`` to be ``index``, with
the additional view predicate requiring a specific request method.
-When a method is decorated multiple times with :class:`~pyramid.view.action`,
-a view configuration will be registered for each call, with the view callable
-being the method decorated. Used with a combination of ``name``, multiple
-URL's can result in different template renderings with the same data.
+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:
diff --git a/docs/narr/hybrid.rst b/docs/narr/hybrid.rst
index b599fefdd..da77a28f0 100644
--- a/docs/narr/hybrid.rst
+++ b/docs/narr/hybrid.rst
@@ -102,7 +102,7 @@ application and a hybrid application:
hybrid application, at least one route will be defined.
- In a purely traversal based application, the root object used is
- global implied by the :term:`root factory` provided at startup
+ global, implied by the :term:`root factory` provided at startup
time; in a hybrid application, the :term:`root` object at which
traversal begins may be varied on a per-route basis.
@@ -207,16 +207,20 @@ the matched route's configuration.
Because the pattern of the above route ends with ``*traverse``, when this
route configuration is matched during a request, :app:`Pyramid`
will attempt to use :term:`traversal` against the :term:`root` object
-implied by the :term:`root factory` implied by the route's
-configuration. Once :term:`traversal` has found a :term:`context`,
+implied by the :term:`root factory` that is implied by the route's
+configuration. Since no ``root_factory`` argument is explicitly specified
+for this route, this will either be the *global* root factory
+for the application, or the *default* root factory.
+Once :term:`traversal` has found a :term:`context`,
:term:`view lookup` will be invoked in almost exactly the same way it
would have been invoked in a "pure" traversal-based application.
-The *default* :term:`root factory` cannot be traversed: it has no
-useful ``__getitem__`` method. So we'll need to associate this route
-configuration with a non-default root factory in order to create a
-useful hybrid application. To that end, let's imagine that we've
-created a root factory that looks like so in a module named
+Let's assume there is no *global* :term:`root factory` configured in
+this application. The *default* :term:`root factory` cannot be traversed:
+it has no useful ``__getitem__`` method. So we'll need to associate
+this route configuration with a custom root factory in order to
+create a useful hybrid application. To that end, let's imagine that
+we've created a root factory that looks like so in a module named
``routes.py``:
.. code-block:: python
@@ -236,7 +240,7 @@ created a root factory that looks like so in a module named
def root_factory(request):
return root
-Above, we've defined a (bogus) graph here that can be traversed, and a
+Above, we've defined a (bogus) graph that can be traversed, and a
``root_factory`` function that can be used as part of a particular
route configuration statement:
@@ -246,20 +250,20 @@ route configuration statement:
config.add_route('home', '{foo}/{bar}/*traverse',
factory='mypackage.routes.root_factory')
-The ``factory`` above points at the function we've defined. It
-will return an instance of the ``Traversable`` class as a root object
-whenever this route is matched. Because the ``Traversable`` object
-we've defined has a ``__getitem__`` method that does something
-nominally useful, and because traversal uses ``__getitem__`` to walk
-the nodes that make up an object graph, using traversal against the
-root object implied by our route statement becomes a reasonable thing
-to do.
+The ``factory`` above points at the function we've defined. It will
+return an instance of the ``Traversable`` class as a root object
+whenever this route is matched. Instances of the``Traversable`` class
+can be used for graph traversal because they have a ``__getitem__``
+method that does something nominally useful. Since traversal uses
+``__getitem__`` to walk the nodes of an object graph, using traversal
+against the root object implied by our route statement is a reasonable
+thing to do.
.. note::
We could have also used our ``root_factory`` callable as the
``root_factory`` argument of the
- :class:`pyramid.config.Configurator` constructor instead
+ :class:`pyramid.config.Configurator` constructor, instead
of associating it with a particular route inside the route's
configuration. Every hybrid route configuration that is matched but
which does *not* name a ``factory`` attribute will use the use
@@ -308,7 +312,7 @@ route's name, in order to indicate that the view should *only be invoked when
the route matches*.
Calls to :meth:`pyramid.config.Configurator.add_view` may pass a
-``route_name`` attribute which refers to the value of an existing route's
+``route_name`` attribute, which refers to the value of an existing route's
``name`` argument. In the above example, the route name is ``home``,
referring to the name of the route defined above it.
@@ -385,7 +389,7 @@ request comes in that causes the route to match in such a way that the
This means that the root object's ``__getitem__`` will be called with
the name ``1`` during the traversal phase. If the ``1`` object
exists, it will become the :term:`context` of the request.
-:ref:`traversal_chapter` has more information about traversal.
+The :ref:`traversal_chapter` chapter has more information about traversal.
If the traversal path contains segment marker names which are not
present in the pattern argument, a runtime error will occur. The
@@ -402,14 +406,15 @@ with this route).
Making Global Views Match
+++++++++++++++++++++++++
-By default, view configurations that don't mention a ``route_name`` will be
-not found by view lookup when a route that mentions a ``*traverse`` in its
-pattern matches. You can make these match forcibly by adding the
-``use_global_views`` flag to the route definition. For example, the
-``myproject.views.bazbuz`` view below will be found if the route named
-``abc`` below is matched and the ``PATH_INFO`` is ``/abc/bazbuz``, even
-though the view configuration statement does not have the
-``route_name="abc"`` attribute.
+By default, only view configurations that mention a ``route_name``
+will be found during view lookup when a route that has a ``*traverse``
+in its pattern matches. You can allow views without a ``route_name``
+attribute to match a route by adding the ``use_global_views`` flag to
+the route definition. For example, the ``myproject.views.bazbuz``
+view below will be found if the route named ``abc`` below is matched
+and the ``PATH_INFO`` is ``/abc/bazbuz``, even though the view
+configuration statement does not have the ``route_name="abc"``
+attribute.
.. code-block:: python
:linenos:
@@ -493,10 +498,10 @@ Can also be spelled like so:
The two spellings are logically equivalent. In fact, the former is
just a syntactical shortcut for the latter.
-Binding Extra Views Against a Route Configuration that Doesn't Have a ``*traverse`` Element In Its Patttern
+Binding Extra Views Against a Route Configuration that Doesn't Have a ``*traverse`` Element In Its Pattern
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Here's another corner case that just makes no sense.
+Here's another corner case that just makes no sense:
.. code-block:: python
:linenos:
@@ -511,7 +516,7 @@ itself (``myproject.views.abc``) will ever be invoked when the route matches,
because the default view is always invoked when a route matches and when no
post-match traversal is performed.
-To make the above view declaration non-useless, the special ``*traverse``
+To make the above view declaration useful, the special ``*traverse``
token must end the route's pattern. For example:
.. code-block:: python
@@ -521,3 +526,8 @@ token must end the route's pattern. For example:
config.add_view('myproject.views.bazbuz', name='bazbuz',
route_name='abc')
+With the above configuration, the ``myproject.views.bazbuz`` view will
+be invoked when the request URI is ``/abc/bazbuz``, assuming there is
+no object contained by the root object with the key ``bazbuz``. A
+different request URI, such as ``/abc/foo/bar``, would invoke the
+default ``myproject.views.abc`` view.
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index db1cfaf9d..abc4f539c 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -86,7 +86,6 @@ the following commands:
[chrism@vitaminf ~]$ mkdir tmp
[chrism@vitaminf ~]$ mkdir opt
[chrism@vitaminf ~]$ cd tmp
- [chrism@vitaminf tmp]$ cd tmp
[chrism@vitaminf tmp]$ wget \
http://www.python.org/ftp/python/2.6.4/Python-2.6.4.tgz
[chrism@vitaminf tmp]$ tar xvzf Python-2.6.4.tgz
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 6cfd31c0b..f8a9017db 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -145,6 +145,17 @@ project we name ``MyProject``:
name during ``paster create`` by adding the project name to the
command line, e.g. ``paster create -t pyramid_starter MyProject``.
+.. note:: You may encounter an error when using ``paster create``
+ if a dependent Python package is not installed. This will
+ result in a traceback ending in:
+
+ .. code-block:: text
+
+ pkg_resources.DistributionNotFound: <package name>
+
+ Simply run ``bin/easy_install``, with the missing package
+ name from the error message, to workaround this issue.
+
As a result of invoking the ``paster create`` command, a project is
created in a directory named ``MyProject``. That directory is a
:term:`setuptools` :term:`project` directory from which a setuptools
@@ -760,7 +771,7 @@ also informs Python that the directory which contains it is a *package*.
:term:`context` of the request is an instance of the
:class:`myproject.models.MyModel` class. The first argument to
``add_view`` points at a Python function that does all the work for this
- view, also known as a :term:`view callable` via a :term:`dotted Python
+ view, also known as a :term:`view callable`, via a :term:`dotted Python
name`. The view declaration also names a ``renderer``, which in this case
is a template that will be used to render the result of the view callable.
This particular view declaration points at
diff --git a/docs/narr/static.rst b/docs/narr/static.rst
index 9547e73fc..172fb08d4 100644
--- a/docs/narr/static.rst
+++ b/docs/narr/static.rst
@@ -1,8 +1,8 @@
Static Resources
================
-:app:`Pyramid` makes it possible to serve up "static" (non-dynamic)
-resources from a directory on a filesystem. This chapter describes
+:app:`Pyramid` makes it possible to serve up static
+resources files from a directory on a filesystem. This chapter describes
how to configure :app:`Pyramid` to do so.
.. index::
@@ -20,7 +20,7 @@ application root URL, e.g. ``/static``.
Note that the ``path`` provided to
:meth:`pyramid.config.Configurator.add_static_view` may be a fully
-qualified :term:`resource specification` or an *absolute path*.
+qualified :term:`resource specification`, or an *absolute path*.
Here's an example of a use of
:meth:`pyramid.config.Configurator.add_static_view` that will serve
@@ -100,7 +100,7 @@ provided with a ``name`` argument that is the URL prefix
``http://example.com/images``, subsequent calls to
:func:`pyramid.url.static_url` with paths that start with the ``path``
argument passed to :meth:`pyramid.config.Configurator.add_static_view`
-will generate a URL something like ``http://example.com/logo.png``. The
+will generate a URL something like ``http://example.com/images/logo.png``. The
external webserver listening on ``example.com`` must be itself configured to
respond properly to such a request. The :func:`pyramid.url.static_url` API
is discussed in more detail later in this chapter.
@@ -110,6 +110,25 @@ to :meth:`pyramid.config.Configurator.add_static_view`. Use of the
:ref:`static_directive` ZCML directive is completely equivalent to using
imperative configuration for the same purpose.
+.. note::
+
+ Using :func:`pyramid.url.static_url` in conjunction with a
+ :meth:`pyramid.configuration.Configurator.add_static_view` makes it
+ possible to put static media on a separate webserver during production (if
+ the ``name`` argument to
+ :meth:`pyramid.configuration.Configurator.add_static_view` is a URL),
+ while keeping static media package-internal and served by the development
+ webserver during development (if the ``name`` argument to
+ :meth:`pyramid.configuration.Configurator.add_static_view` is a view
+ name). To create such a circumstance, we suggest using the
+ :attr:`pyramid.registry.Registry.settings` API in conjunction with a
+ setting in the application ``.ini`` file named ``media_location``. Then
+ set the value of ``media_location`` to either a view name or a URL
+ depending on whether the application is being run in development or in
+ production (use a different `.ini`` file for production than you do for
+ development). This is just a suggestion for a pattern; any setting name
+ other than ``media_location`` could be used.
+
.. index::
single: generating static resource urls
single: static resource urls
@@ -133,8 +152,8 @@ For example, let's assume you create a set of static declarations like so:
config.add_static_view(name='static1', path='mypackage:resources/1')
config.add_static_view(name='static2', path='mypackage:resources/2')
-These declarations create URL-accessible directories which have URLs which
-begin, respectively, with ``/static1`` and ``/static2``. The resources in
+These declarations create URL-accessible directories which have URLs that
+begin with ``/static1`` and ``/static2``, respectively. The resources in
the ``resources/1`` directory of the ``mypackage`` package are consulted when
a user visits a URL which begins with ``/static1``, and the resources in the
``resources/2`` directory of the ``mypackage`` package are consulted when a
@@ -178,7 +197,7 @@ instead of a view name. For example, the ``name`` argument may be
.. code-block:: python
:linenos:
- config.add_static_view(name='static1', path='mypackage:images')
+ config.add_static_view(name='http://example.com/images', path='mypackage:images')
Under such a configuration, the URL generated by ``static_url`` for
resources which begin with ``mypackage:images`` will be prefixed with
@@ -206,7 +225,7 @@ The :class:`pyramid.view.static` helper class is used to perform
this task. This class creates an object that is capable acting as a
:app:`Pyramid` view callable which serves static resources from a
directory. For instance, to serve files within a directory located on
-your filesystem at ``/path/to/static/dir`` mounted at the URL path
+your filesystem at ``/path/to/static/dir`` from the URL path
``/static`` in your application, create an instance of the
:class:`pyramid.view.static` class inside a ``static.py`` file in
your application root as below.
@@ -219,13 +238,10 @@ your application root as below.
static_view = static('/path/to/static/dir')
.. note:: the argument to :class:`pyramid.view.static` can also be
- a relative pathname, e.g. ``my/static`` (meaning relative to the
+ a "here-relative" pathname, e.g. ``my/static`` (meaning relative to the
Python package of the module in which the view is being defined).
It can also be a :term:`resource specification`
- (e.g. ``anotherpackage:some/subdirectory``) or it can be a
- "here-relative" path (e.g. ``some/subdirectory``). If the path is
- "here-relative", it is relative to the package of the module in
- which the static view is defined.
+ (e.g. ``anotherpackage:some/subdirectory``).
Subsequently, you may wire this view up to be accessible as ``/static`` using
the :mod:`pyramid.config.Configurator.add_view` method in your
@@ -238,25 +254,33 @@ represents your root object.
config.add_view('mypackage.static.static_view', name='static',
context='mypackage.models.Root')
-In this case, ``mypackage.models.Root`` refers to the class of which your
-:app:`Pyramid` application's root object is an instance.
+In this case, ``mypackage.models.Root`` refers to the class of your
+:app:`Pyramid` application's traversal root object.
-You can also omit the ``context`` argument if you want the name ``static`` to
-be accessible as the static view against any model. This will also allow
-``/static/foo.js`` to work, but it will allow for ``/anything/static/foo.js``
-too, as long as ``anything`` itself is resolvable.
+The context argument above limits where the static view is accessible to
+URL paths directly under the root object. If you omit the ``context``
+argument, then ``static`` will be accessible as the static view against
+any model object in the traversal graph. This will allow
+``/static/foo.js`` to work, but it will also allow for
+``/anything/static/foo.js`` too, as long as ``anything`` can be
+resolved.
Note that you cannot use the :func:`pyramid.url.static_url` API to generate
URLs against resources made accessible by registering a custom static view.
.. warning::
- To ensure that model objects contained in the root don't "shadow"
- your static view (model objects take precedence during traversal),
- or to ensure that your root object's ``__getitem__`` is never
- called when a static resource is requested, you can refer to your
- static resources as registered above in URLs as,
- e.g. ``/@@static/foo.js``. This is completely equivalent to
- ``/static/foo.js``. See :ref:`traversal_chapter` for information
+ When adding a static view to your root object, you need to be
+ careful that there are no model objects contained in the
+ root with the same key as the view name (e.g., ``static``).
+ Model objects take precedence during traversal,
+ thus such a name collision will cause the model to "shadow"
+ your static view. To avoid this issue, and ensure that your
+ root object's ``__getitem__`` is never
+ called when a static resource is requested, you can refer to them
+ unambiguously using the ``@@`` prefix (goggles) in their URLs.
+ For the above examples you could use '/@@static/foo.js'
+ instead of '/static/foo.js' to avoid such shadowing.
+ See :ref:`traversal_chapter` for information
about "goggles" (``@@``).
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index 3d109218e..01729c4bd 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -360,7 +360,7 @@ and a :term:`view name`.
of path segments that come from ``PATH_INFO`` that are "left over"
after traversal has completed.
-Once :term:`context` and :term:`view name` and associated attributes
+Once :term:`context`, :term:`view name`, and associated attributes
such as the :term:`subpath` are located, the job of :term:`traversal`
is finished. It passes back the information it obtained to its
caller, the :app:`Pyramid` :term:`Router`, which subsequently
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 5d8dae1c5..c84a5ca06 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -96,7 +96,7 @@ registry`. Here's an example:
.. versionchanged:: 1.0a4
Prior to 1.0a4, routes allow for a marker starting with a ``:``, for
- example ``/prefix/{one}``. Starting in 1.0a4, this style is deprecated
+ example ``/prefix/:one/:two``. Starting in 1.0a4, this style is deprecated
in favor or ``{}`` usage which allows for additional functionality.
.. index::
@@ -179,12 +179,12 @@ during a request. To do so:
to service requests that match the route pattern.
In this way, we supply a shortcut to the developer. Under the hood,
-:app:`Pyramid` still consumes the :term:`context finding` and
-:term:`view lookup` subsystems provided by :app:`Pyramid`, but in a
-way which does not require that a developer understand either of them
-if he doesn't want or need to. It also means that we can allow a
-developer to combine :term:`URL dispatch` and :term:`traversal` in
-various exceptional cases as documented in :ref:`hybrid_chapter`.
+the :term:`context finding` and :term:`view lookup` subsystems
+provided by :app:`Pyramid` are still being utilized, but in a way
+which does not require a developer to understand either of them in
+detail. It also means that we can allow a developer to combine
+:term:`URL dispatch` and :term:`traversal` in various exceptional
+cases as documented in :ref:`hybrid_chapter`.
.. index::
single: route path pattern syntax
@@ -263,15 +263,15 @@ To capture both segments, two replacement markers can be used:
foo/{name}.{ext}
-The literal path ``/foo/biz.html`` will match the above route pattern, and the
-match result will be ``{'name': 'biz', 'ext': 'html'}``. This occurs because
-the replacement marker ``{name}`` has a literal part of ``.`` between the other
-replacement marker ``:ext``.
+The literal path ``/foo/biz.html`` will match the above route pattern,
+and the match result will be ``{'name': 'biz', 'ext': 'html'}``. This
+occurs because the replacement marker ``{name}`` has a literal part of
+``.`` (period) between the other replacement marker ``{ext}``.
-It is possible to use two replacement markers without any literal characters
-between them, for instance ``/{foo}{bar}``. This would be a nonsensical pattern
-without specifying a custom regular expression to restrict what a marker
-captures.
+It is possible to use two replacement markers without any literal
+characters between them, for instance ``/{foo}{bar}``. However, this
+would be a nonsensical pattern without specifying a custom regular
+expression to restrict what each marker captures.
Segments must contain at least one character in order to match a
segment replacement marker. For example, for the URL ``/abc/``:
@@ -281,7 +281,7 @@ segment replacement marker. For example, for the URL ``/abc/``:
- ``/{foo}/`` will match.
Note that values representing path segments matched with a
-``:segment`` match will be url-unquoted and decoded from UTF-8 into
+``{segment}`` match will be url-unquoted and decoded from UTF-8 into
Unicode within the matchdict. So for instance, the following
pattern:
@@ -358,7 +358,7 @@ matchdicts:
foo/abc/def/a/b/c -> {'baz':'abc', 'bar':'def', 'fizzle': 'a/b/c')}
This occurs because the default regular expression for a marker is ``[^/]+``
-which will match everything up to the first ``/``, while ``{filzzle:.*}`` will
+which will match everything up to the first ``/``, while ``{fizzle:.*}`` will
result in a regular expression match of ``.*`` capturing the remainder into
a single value.
@@ -368,9 +368,9 @@ a single value.
Route Declaration Ordering
~~~~~~~~~~~~~~~~~~~~~~~~~~
-Because route configuration declarations are evaluated in a specific
-order when a request enters the system, route configuration
-declaration ordering is very important.
+Route configuration declarations are evaluated in a specific
+order when a request enters the system. As a result, the
+order of route configuration declarations is very important.
The order that routes declarations are evaluated is the order in which
they are added to the application at startup time. This is unlike
@@ -390,7 +390,7 @@ be added in the following order:
members/abc
In such a configuration, the ``members/abc`` pattern would *never* be
-matched; this is because the match ordering will always match
+matched. This is because the match ordering will always match
``members/{def}`` first; the route configuration with ``members/abc``
will never be evaluated.
@@ -417,7 +417,7 @@ found via :term:`view lookup`.
factory='myproject.models.root_factory')
The factory can either be a Python object or a :term:`dotted Python name` (a
-string) which points to such a Python oject, as it is above.
+string) which points to such a Python object, as it is above.
In this way, each route can use a different factory, making it
possible to supply a different :term:`context` object to the view
@@ -425,8 +425,8 @@ related to each particular route.
Supplying a different context for each route is useful when you're
trying to use a :app:`Pyramid` :term:`authorization policy` to
-provide declarative "context-sensitive" security checks; each context
-can maintain a separate :term:`ACL`, as in
+provide declarative, "context sensitive" security checks; each context
+can maintain a separate :term:`ACL`, as documented in
:ref:`using_security_with_urldispatch`. It is also useful when you
wish to combine URL dispatch with :term:`traversal` as documented
within :ref:`hybrid_chapter`.
@@ -1080,12 +1080,14 @@ Redirecting to Slash-Appended Routes
------------------------------------
For behavior like Django's ``APPEND_SLASH=True``, use the
-:func:`pyramid.view.append_slash_notfound_view` view as the
-:term:`Not Found view` in your application. When this view is the Not
-Found view (indicating that no view was found), and any routes have
-been defined in the configuration of your application, if the value of
-``PATH_INFO`` does not already end in a slash, and if the value of
-``PATH_INFO`` *plus* a slash matches any route's pattern, it does an
+:func:`pyramid.view.append_slash_notfound_view` view as the :term:`Not
+Found view` in your application. Defining this view as the :term:`Not
+Found view` is a way to automatically redirect requests where the URL
+lacks a trailing slash, but requires one to match the proper route.
+When configured, along with at least one other route in your
+application, this view will be invoked if the value of ``PATH_INFO``
+does not already end in a slash, and if the value of ``PATH_INFO``
+*plus* a slash matches any route's pattern. In this case it does an
HTTP redirect to the slash-appended ``PATH_INFO``.
Let's use an example, because this behavior is a bit magical. If the
@@ -1098,20 +1100,24 @@ your route configuration looks like so:
config.add_route('noslash', 'no_slash', view='myproject.views.no_slash')
config.add_route('hasslash', 'has_slash/', view='myproject.views.has_slash')
+If a request enters the application with the ``PATH_INFO``
+value of ``/has_slash/``, the second route will match. If a request
+enters the application with the ``PATH_INFO`` value of ``/has_slash``,
+a route *will* be found by the slash-appending not found view. An HTTP
+redirect to ``/has_slash/`` will be returned to the user's browser.
+
If a request enters the application with the ``PATH_INFO`` value of
-``/no_slash``, the first route will match. If a request enters the
+``/no_slash``, the first route will match. However, if a request enters the
application with the ``PATH_INFO`` value of ``/no_slash/``, *no* route
-will match, and the slash-appending "not found" view will *not* find a
+will match, and the slash-appending not found view will *not* find a
matching route with an appended slash.
-However, if a request enters the application with the ``PATH_INFO``
-value of ``/has_slash/``, the second route will match. If a request
-enters the application with the ``PATH_INFO`` value of ``/has_slash``,
-a route *will* be found by the slash appending notfound view. An HTTP
-redirect to ``/has_slash/`` will be returned to the user's browser.
+.. warning::
-Note that this will *lose* ``POST`` data information (turning it into
-a GET), so you shouldn't rely on this to redirect POST requests.
+ You **should not** rely on this mechanism to redirect ``POST`` requests.
+ The redirect of the slash-appending not found view will turn a ``POST``
+ request into a ``GET``, losing any ``POST`` data in the original
+ request.
To configure the slash-appending not found view in your application, change
the application's startup configuration, adding the following stanza:
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index fee341634..8a689be21 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -18,7 +18,7 @@ a request made to your application.
that implements a view *callable*, and the process of view
*lookup*.
-The chapter named :ref:`contextfinding_chapter` describes how, using
+The chapter :ref:`contextfinding_chapter` describes how, using
information from the :term:`request`, a :term:`context` and a
:term:`view name` are computed. But neither the context nor the view
name found are very useful unless those elements can eventually be
@@ -47,15 +47,13 @@ represents a :app:`Pyramid` :term:`Request` object. A request object
encapsulates a WSGI environment as represented to :app:`Pyramid` by the
upstream :term:`WSGI` server.
-A view callable may always return a :mod:`Pyramid` :term:`Response` object
-directly. It may optionally return another arbitrary non-Response value: if a
-view callable returns a non-Response result, the result must be converted into
-a response by the :term:`renderer` associated with the :term:`view
+A view callable can return a :mod:`Pyramid` :term:`Response` object
+directly. It may return another arbitrary non-Response value,
+however, this return value must be converted into a :term:`Response`
+object by the :term:`renderer` associated with the :term:`view
configuration` for the view.
-View callables can be functions, instances, or classes. View
-callables can optionally be defined with an alternate calling
-convention.
+View callables can be functions, instances, or classes.
.. index::
single: view calling convention
@@ -67,7 +65,7 @@ Defining a View Callable as a Function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The easiest way to define a view callable is to create a function that
-accepts a single argument named ``request`` and which returns a
+accepts a single argument named ``request``, and which returns a
:term:`Response` object. For example, this is a "hello world" view
callable implemented as a function:
@@ -97,10 +95,7 @@ created. Subsequently, that instance's ``__call__`` method is invoked
with no parameters. Views defined as classes must have the following
traits:
-- an ``__init__`` method that accepts a ``request`` as its sole
- positional argument or an ``__init__`` method that accepts two
- arguments: ``request`` and ``context`` as per
- :ref:`request_and_context_view_definitions`.
+- an ``__init__`` method that accepts a ``request`` argument.
- a ``__call__`` method that accepts no parameters and which returns a
response.
@@ -132,75 +127,74 @@ represent the method expected to return a response, you can use an
.. _request_and_context_view_definitions:
-Context-And-Request View Callable Definitions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. sidebar:: Context-And-Request View Callable Definitions
-Usually, view callables are defined to accept only a single argument:
-``request``. However, view callables may alternately be defined as
-classes or functions (or any callable) that accept *two* positional
-arguments: a :term:`context` as the first argument and a
-:term:`request` as the second argument.
+ Usually, view callables are defined to accept only a single argument:
+ ``request``. However, view callables may alternately be defined as
+ classes, functions, or any callable that accept *two* positional
+ arguments: a :term:`context` as the first argument and a
+ :term:`request` as the second argument.
-The :term:`context` and :term:`request` arguments passed to a view
-function defined in this style can be defined as follows:
+ The :term:`context` and :term:`request` arguments passed to a view
+ function defined in this style can be defined as follows:
-context
- An instance of a :term:`context` found via graph :term:`traversal`
- or :term:`URL dispatch`. If the context is found via traversal, it
- will be a :term:`model` object.
+ context
+ An instance of a :term:`context` found via graph :term:`traversal`
+ or :term:`URL dispatch`. If the context is found via traversal, it
+ will be a :term:`model` object.
-request
- A :app:`Pyramid` Request object representing the current WSGI
- request.
+ request
+ A :app:`Pyramid` Request object representing the current WSGI
+ request.
-The following types work as view callables in this style:
+ The following types work as view callables in this style:
-#. Functions that accept two arguments: ``context``, and ``request``,
- e.g.:
+ #. Functions that accept two arguments: ``context``, and ``request``,
+ e.g.:
- .. code-block:: python
- :linenos:
+ .. code-block:: python
+ :linenos:
- from pyramid.response import Response
+ from pyramid.response import Response
- def view(context, request):
- return Response('OK')
+ def view(context, request):
+ return Response('OK')
-#. Classes that have an ``__init__`` method that accepts ``context,
- request`` and a ``__call__`` which accepts no arguments, e.g.:
+ #. Classes that have an ``__init__`` method that accepts ``context,
+ request`` and a ``__call__`` which accepts no arguments, e.g.:
- .. code-block:: python
- :linenos:
+ .. code-block:: python
+ :linenos:
- from pyramid.response import Response
+ from pyramid.response import Response
- class view(object):
- def __init__(self, context, request):
- self.context = context
- self.request = request
+ class view(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
- def __call__(self):
- return Response('OK')
+ def __call__(self):
+ return Response('OK')
-#. Arbitrary callables that have a ``__call__`` method that accepts
- ``context, request``, e.g.:
+ #. Arbitrary callables that have a ``__call__`` method that accepts
+ ``context, request``, e.g.:
- .. code-block:: python
- :linenos:
+ .. code-block:: python
+ :linenos:
- from pyramid.response import Response
+ from pyramid.response import Response
- class View(object):
- def __call__(self, context, request):
- return Response('OK')
- view = View() # this is the view callable
+ class View(object):
+ def __call__(self, context, request):
+ return Response('OK')
+ view = View() # this is the view callable
-This style of calling convention is most useful for :term:`traversal`
-based applications, where the context object is frequently used within
-the view callable code itself.
+ This style of calling convention is most useful for :term:`traversal`
+ based applications, where the context object is frequently used within
+ the view callable code itself.
-No matter which view calling convention is used, the view code always
-has access to the context via ``request.context``.
+ No matter which view calling convention is used, the view code always
+ has access to the context via ``request.context``.
.. index::
single: view response
@@ -288,8 +282,8 @@ and renderers which use templating systems. See also
.. _http_redirect:
-Using a View Callable to Do A 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.
@@ -308,6 +302,19 @@ See :mod:`pyramid.httpexceptions` for the documentation for the ``HTTPFound``
exception; it also includes other response types that imply other HTTP response
codes, such as ``HTTPUnauthorized`` for ``401 Unauthorized``.
+.. note::
+
+ Although exception types from the :mod:`pyramid.httpexceptions` module are
+ in fact bona fide Python :class:`Exception` types, the :app:`Pyramid` view
+ machinery expects them to be *returned* by a view callable rather than
+ *raised*.
+
+ It is possible, however, in Python 2.5 and above, to configure an
+ *exception view* to catch these exceptions, and return an appropriate
+ :class:`pyramid.response.Response`. The simplest such view could just
+ catch and return the original exception. See :ref:`exception_views` for
+ more details.
+
.. index::
single: renderer
single: view renderer
@@ -379,7 +386,7 @@ Additional renderers can be added to the system as necessary (see
Built-In Renderers
~~~~~~~~~~~~~~~~~~
-Several built-in "renderers" exist in :app:`Pyramid`. These
+Several built-in renderers exist in :app:`Pyramid`. These
renderers can be used in the ``renderer`` attribute of view
configurations.
@@ -429,14 +436,13 @@ attributes by attaching properties to the request. See
``json``: JSON Renderer
+++++++++++++++++++++++
-The ``json`` renderer is a renderer which renders view callable
-results to :term:`JSON`. If a view callable returns a non-Response
-object it is called. It passes the return value through the
+The ``json`` renderer renders view callable
+results to :term:`JSON`. It passes the return value through the
``json.dumps`` standard library function, and wraps the result in a
response object. It also sets the response content-type to
``application/json``.
-Here's an example of a view that returns a dictionary. If the
+Here's an example of a view that returns a dictionary. Since the
``json`` renderer is specified in the configuration for this view, the
view will render the returned dictionary to a JSON serialization:
@@ -561,19 +567,21 @@ attaching properties to the request. See
``*.mak`` or ``*.mako``: Mako Template Renderer
+++++++++++++++++++++++++++++++++++++++++++++++
-The ``Mako`` template renderer is a renderer which renders a Mako template.
+The ``Mako`` template renderer renders views using a Mako template.
When used, the view must return a Response object or a Python *dictionary*.
The dictionary items will then be used in the global template space. If the
-view callable returns anything but a Response object or a dictionary, an error
+view callable returns anything but a Response object, or a dictionary, an error
will be raised.
-When using the ``renderer`` attribute to specify a Mako template, the template
-can be specified in two ways. First, a relative path can be used to name a
-Mako template relative to the configured Mako template directories. Second, a
-:term:`resource specification` can be used to locate a template to render.
-These two styles of naming a template to render also carry through to Mako
-templates, so that Mako template's can inherit using a :term:`resource
-specification` if desired.
+When using a ``renderer`` argument to a :term:`view configuration` to
+specify a Mako template, the value of the ``renderer`` may be a path
+relative to the ``mako.directories`` setting (e.g.
+``some/template.mak``) or, alternately, it may be a :term:`resource
+specification` (e.g. ``apackage:templates/sometemplate.mak``). Mako
+templates may internally inherit other Mako templates using a relative
+filename or a :term:`resource specification` as desired.
+
+XXX Further explanation or link to mako inheritance info
Here's an example view configuration which uses a relative path:
@@ -620,14 +628,13 @@ additional :ref:`mako_template_renderer_settings`.
Varying Attributes of Rendered Responses
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Before a response that is constructed as the result of the use of a
-:term:`renderer` is returned to :app:`Pyramid`, several attributes
-of the request are examined which have the potential to influence
-response behavior.
+Before a response constructed by a :term:`renderer` is returned to
+:app:`Pyramid`, several attributes of the request are examined which
+have the potential to influence response behavior.
View callables that don't directly return a response should set these
-values on the ``request`` object via ``setattr`` within the view
-callable to influence associated response attributes.
+attributes on the ``request`` object via ``setattr`` during their
+execution, to influence associated response attributes.
``response_content_type``
Defines the content-type of the resulting response,
@@ -678,7 +685,7 @@ Adding and Overriding Renderers
New templating systems and serializers can be associated with :app:`Pyramid`
renderer names. To this end, configuration declarations can be made which
-override an existing :term:`renderer factory` and which add a new renderer
+override an existing :term:`renderer factory`, and which add a new renderer
factory.
Renderers can be registered imperatively using the
@@ -707,10 +714,10 @@ to such an object.
Adding a New Renderer
+++++++++++++++++++++
-You may a new renderer by creating and registering a :term:`renderer
+You may add a new renderer by creating and registering a :term:`renderer
factory`.
-A renderer factory implementation is usually a class which has the
+A renderer factory implementation is typically a class with the
following interface:
.. code-block:: python
@@ -739,8 +746,8 @@ factory constructor is available as :class:`pyramid.interfaces.IRendererInfo`.
There are essentially two different kinds of renderer factories:
-- A renderer factory which expects to accept a :term:`resource specification`
- or an absolute path as the ``name`` attribute of the ``info`` object fed to
+- A renderer factory which expects to accept a :term:`resource specification`,
+ or an absolute path, as the ``name`` attribute of the ``info`` object fed to
its constructor. These renderer factories are registered with a ``name``
value that begins with a dot (``.``). These types of renderer factories
usually relate to a file on the filesystem, such as a template.
@@ -770,10 +777,11 @@ Here's an example of the registration of a simple renderer factory via
config.add_renderer(name='amf', factory='my.package.MyAMFRenderer')
-Adding the above code to your application startup configuration will allow
-you to use the ``my.package.MyAMFRenderer`` renderer factory implementation
-in view configurations by referring to it as ``amf`` in the ``renderer``
-attribute of a :term:`view configuration`:
+Adding the above code to your application startup configuration will
+allow you to use the ``my.package.MyAMFRenderer`` renderer factory
+implementation in view configurations. Your application can use this
+renderer by specifying ``amf`` in the ``renderer`` attribute of a
+:term:`view configuration`:
.. code-block:: python
:linenos:
@@ -784,13 +792,12 @@ attribute of a :term:`view configuration`:
def myview(request):
return {'Hello':'world'}
-At startup time, when a :term:`view configuration` is encountered
-which has a ``name`` argument that does not contain a dot, such as the
-above ``amf`` is encountered, the full value of the ``name`` attribute
-is used to construct a renderer from the associated renderer factory.
-In this case, the view configuration will create an instance of an
-``AMFRenderer`` for each view configuration which includes ``amf`` as
-its renderer value. The ``name`` passed to the ``AMFRenderer``
+At startup time, when a :term:`view configuration` is encountered, which
+has a ``name`` attribute that does not contain a dot, the full ``name``
+value is used to construct a renderer from the associated renderer
+factory. In this case, the view configuration will create an instance
+of an ``AMFRenderer`` for each view configuration which includes ``amf``
+as its renderer value. The ``name`` passed to the ``AMFRenderer``
constructor will always be ``amf``.
Here's an example of the registration of a more complicated renderer
@@ -816,17 +823,17 @@ the ``renderer`` attribute of a :term:`view configuration`:
def myview(request):
return {'Hello':'world'}
-When a :term:`view configuration` which has a ``name`` attribute that does
-contain a dot, such as ``templates/mytemplate.jinja2`` above is encountered
-at startup time, the value of the name attribute is split on its final dot.
-The second element of the split is typically the filename extension. This
-extension is used to look up a renderer factory for the configured view.
-Then the value of ``renderer`` is passed to the factory to create a renderer
-for the view. In this case, the view configuration will create an instance
-of a ``Jinja2Renderer`` for each view configuration which includes anything
-ending with ``.jinja2`` as its ``renderer`` value. The ``name`` passed to
-the ``Jinja2Renderer`` constructor will be whatever the user passed as
-``renderer=`` to the view configuration.
+When a :term:`view configuration` is encountered at startup time, which
+has a ``name`` attribute that does contain a dot, the value of the name
+attribute is split on its final dot. The second element of the split is
+typically the filename extension. This extension is used to look up a
+renderer factory for the configured view. Then the value of
+``renderer`` is passed to the factory to create a renderer for the view.
+In this case, the view configuration will create an instance of a
+``Jinja2Renderer`` for each view configuration which includes anything
+ending with ``.jinja2`` in its ``renderer`` value. The ``name`` passed
+to the ``Jinja2Renderer`` constructor will be the full value that was
+set as ``renderer=`` in the view configuration.
See also :ref:`renderer_directive` and
:meth:`pyramid.config.Configurator.add_renderer`.
@@ -861,9 +868,9 @@ After you do this, the :term:`renderer factory` in
``mypackage.pt_renderer`` will be used to render templates which end
in ``.pt``, replacing the default Chameleon ZPT renderer.
-To associate a *default* renderer with *all* view configurations (even ones
-which do not possess a ``renderer`` attribute), use a variation on the
-following (ie. pass ``None`` as the ``name`` attribute to the renderer tag):
+To associate a *default* renderer with *all* view configurations (even
+ones which do not possess a ``renderer`` attribute), pass ``None`` as
+the ``name`` attribute to the renderer tag:
.. code-block:: python
:linenos:
@@ -970,25 +977,24 @@ The above exception view names the ``route_name`` of ``home``, meaning
that it will only be called when the route matched has a name of
``home``. You can therefore have more than one exception view for any
given exception in the system: the "most specific" one will be called
-when the set of request circumstances which match the view
-registration.
+when the set of request circumstances match the view registration.
-The only view predicate that cannot be not be used successfully when
-creating an exception view configuration is ``name``. The name used
-to look up an exception view is always the empty string. Views
-registered as exception views which have a name will be ignored.
+The only view predicate that cannot be used successfully when creating
+an exception view configuration is ``name``. The name used to look up
+an exception view is always the empty string. Views registered as
+exception views which have a name will be ignored.
.. note::
- Normal (non-exception) views registered against a context which
+ Normal (i.e., non-exception) views registered against a context which
inherits from :exc:`Exception` will work normally. When an
- exception view configuraton is processed, *two* views are
+ exception view configuration is processed, *two* views are
registered. One as a "normal" view, the other as an "exception"
view. This means that you can use an exception as ``context`` for a
normal view.
-The feature can be used with any view registration mechanism
-(``@view_config`` decorator, ZCML, or imperative ``add_view`` styles).
+Exception views can be configured with any view registration mechanism:
+``@view_config`` decorator, ZCML, or imperative ``add_view`` styles.
.. index::
single: unicode, views, and forms
@@ -1010,19 +1016,29 @@ 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. Because having high-order
-(non-ASCII) characters in data contained within form submissions is exceedingly
-common, and because the UTF-8 encoding is the most common encoding used on the
-web for non-ASCII character data, and because working and storing Unicode
-values is much saner than working with and storing bytestrings, :app:`Pyramid`
+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 the UTF-8 character set 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).
+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).
-For example, let's assume that the following form page is served up to
+.. 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 transmittal 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:
@@ -1069,22 +1085,24 @@ decode already-decoded (``unicode``) values obtained from
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 is rendered 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 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. The browser client may have a non-UTF-8 default encoding. If
-such a request is handled by your view code, when the form submission data is
-encoded in a non-UTF8 charset, 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
+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
@@ -1092,14 +1110,14 @@ 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``,
+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 strings.
+ configuration. The keys are still (byte) strings.
.. index::
single: view configuration
@@ -1112,7 +1130,7 @@ View Configuration: Mapping a Context to a View
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
-about the set of circumstances which must be true for the view
+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
@@ -1246,6 +1264,10 @@ Non-Predicate Arguments
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.
@@ -1254,7 +1276,7 @@ Predicate Arguments
default view).
``context``
- An object representing Python class that the :term:`context` must be
+ An object representing a Python class that the :term:`context` must be
an instance of, *or* the :term:`interface` that the :term:`context`
must provide in order for this view to be found and called. This
predicate is true when the :term:`context` is an instance of the
@@ -1271,14 +1293,15 @@ Predicate Arguments
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`` usually has 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
+ 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 for when the :term:`triad` includes a
- request object that does not indicate it matched a route.
+ chance of being invoked if no other route was matched. This is when
+ the request object of the :term:`triad` does not indicate it matched
+ any configured route.
``request_type``
This value should be an :term:`interface` that the :term:`request`
@@ -1319,9 +1342,10 @@ Predicate Arguments
``containment``
This value should be a reference to a Python class or
- :term:`interface` that a parent object in the :term:`lineage` must
- provide in order for this view to be found and called. The nodes in
- your object graph must be "location-aware" to use this feature.
+ :term:`interface` that a parent object in the context's
+ :term:`lineage` must provide in order for this view to be found and
+ called. The nodes in your object graph 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
@@ -1480,11 +1504,13 @@ All arguments to ``view_config`` may be omitted. For example:
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 model type, using no permission, registered against
-requests with any request method / request type / request param /
-route name / containment.
+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. To make :app:`Pyramid` process your
+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`:
@@ -1602,7 +1628,7 @@ 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`` as per :ref:`request_and_context_view_definitions`.
+request``.
The method which is decorated must return a :term:`response` or it
must rely on a :term:`renderer` to generate one.
@@ -1721,12 +1747,12 @@ in such a way that the interface is attached to it.
alsoProvides(hello, IHello)
return hello
-Regardless of how you associate an interface with a model instance or a model
+Regardless of how you associate an interface, with a model instance, or a model
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 "models.py", the
-below interface declaration will associate the
-``mypackage.views.hello_world`` view with models that implement (aka provide)
+interface declaration below will associate the
+``mypackage.views.hello_world`` view with models that implement, or provide,
this interface.
.. code-block:: python
@@ -1741,11 +1767,13 @@ Any time a model 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 that views registered against a model class take precedence over views
-registered for any interface the model class implements when an ambiguity
-arises. If a view is registered for both the class type of the context and
-an interface implemented by the context's class, the view registered for the
-context's class will "win".
+Note, in cases where a view is registered against a model class, and a
+view is also registered against an interface that the model class
+implements, an ambiguity arises. Views registered for the model class
+take precedence over any views registered for any interface the model
+class implements. Thus, if a view is registered for both the class type
+of the context and an interface implemented by the context's class, the
+view registered for the context's class will "win".
For more information about defining models with interfaces for use within
view configuration, see :ref:`models_which_implement_interfaces`.
@@ -1759,12 +1787,22 @@ view configuration, see :ref:`models_which_implement_interfaces`.
Configuring View Security
~~~~~~~~~~~~~~~~~~~~~~~~~
+<<<<<<< HEAD
+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` before the view
+function is actually called. Here's an example of specifying a
+permission in a view configuration using
+:meth:`pyramid.configuration.Configurator.add_view`:
+=======
If a :term:`authorization policy` is active, any :term:`permission` attached
to a :term:`view configuration` found during view lookup will be consulted to
ensure that the currently authenticated user possesses that permission
against the :term:`context` 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`:
+>>>>>>> fee38663daccc0130d0c34dbc5a14e67bef2e183
.. code-block:: python
:linenos:
@@ -1774,11 +1812,11 @@ Here's an example of specifying a permission in a view configuration using
config.add_view('myproject.views.add_entry', name='add.html',
context='myproject.models.IBlog', permission='add')
-When an authentication 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` and an
-authorization policy is enabled. Instead the :term:`forbidden view` result
-will be returned to the client as per :ref:`protecting_views`.
+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
@@ -1792,7 +1830,7 @@ View Lookup and Invocation
finding an invoking a :term:`view callable`. The view lookup
subsystem is passed a :term:`context`, a :term:`view name`, and the
:term:`request` object. These three bits of information are referred
-to within this chapter as a :term:`triad`.
+to within this chapter as the :term:`triad`.
:term:`View configuration` information stored within in the
:term:`application registry` is compared against a triad by the view
@@ -1817,7 +1855,7 @@ 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 which has predicates which allow it to be
+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
@@ -1839,5 +1877,5 @@ misconfiguration. To debug these errors, use the
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.
+more information about how, and where to set these values.
diff --git a/docs/narr/webob.rst b/docs/narr/webob.rst
index c4805df8d..83d096a57 100644
--- a/docs/narr/webob.rst
+++ b/docs/narr/webob.rst
@@ -111,8 +111,8 @@ Special Attributes Added to the Request by :app:`Pyramid`
In addition to the standard :term:`WebOb` attributes, :app:`Pyramid`
adds special attributes to every request: ``context``, ``registry``,
-``root``, ``subpath``, ``traversed``, ``view_name``, ``virtual_root``
-, ``virtual_root_path``, ``session``, and ``tmpl_context``. These
+``root``, ``subpath``, ``traversed``, ``view_name``, ``virtual_root``,
+``virtual_root_path``, ``session``, and ``tmpl_context``. These
attributes are documented further within the
:class:`pyramid.request.Request` API documentation.
@@ -183,7 +183,7 @@ only a few you'll use often:
``req.get_response(wsgi_application)``:
This method calls the given WSGI application with this request,
and returns a `Response`_ object. You can also use this for
- subrequests or testing.
+ subrequests, or testing.
.. index::
single: request (and unicode)
@@ -203,8 +203,8 @@ attribute.
If it is set, then ``req.POST``, ``req.GET``, ``req.params``, and
``req.cookies`` will contain unicode strings. Each has a
-corresponding ``req.str_*`` (like ``req.str_POST``) that is always
-``str`` and never unicode.
+corresponding ``req.str_*`` (e.g., ``req.str_POST``) that is always
+a ``str``, and never unicode.
More Details
++++++++++++
@@ -213,9 +213,9 @@ More detail about the request object API is available in:
- The :class:`pyramid.request.Request` API documentation.
-- The `WebOb documentation <http://pythonpaste.org/webob>`_ . All
+- The `WebOb documentation <http://pythonpaste.org/webob>`_. All
methods and attributes of a ``webob.Request`` documented within the
- WebOb documentation will work against request objects created by
+ WebOb documentation will work with request objects created by
:app:`Pyramid`.
.. index::
@@ -231,8 +231,9 @@ for its original location: ``webob.Response``.
A response object has three fundamental parts:
``response.status``:
- The response code plus message, like ``'200 OK'``. To set the
- code without the reason, use ``response.status_int = 200``.
+ The response code plus reason message, like ``'200 OK'``. To set
+ the code without a message, use ``status_int``, i.e.:
+ ``response.status_int = 200``.
``response.headerlist``:
A list of all the headers, like ``[('Content-Type',
@@ -325,7 +326,7 @@ Exception Responses
To facilitate error responses like ``404 Not Found``, the module
:mod:`webob.exc` contains classes for each kind of error response. These
-include boring but appropriate error bodies. The exceptions exposed by this
+include boring, but appropriate error bodies. The exceptions exposed by this
module, when used under :app:`Pyramid`, should be imported from the
:mod:`pyramid.httpexceptions` "facade" module. This import location is merely
a facade for the original location of these exceptions: ``webob.exc``.