summaryrefslogtreecommitdiff
path: root/docs/narr
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2008-11-14 04:06:31 +0000
committerChris McDonough <chrism@agendaless.com>2008-11-14 04:06:31 +0000
commit672f977604a0d57bb3419dbadee8fd92b48ba694 (patch)
tree54e8800041d874904dfbbe3804b9129c5e48c478 /docs/narr
parent38b6635fd101e51717d2daf7cc35f09590536cda (diff)
downloadpyramid-672f977604a0d57bb3419dbadee8fd92b48ba694.tar.gz
pyramid-672f977604a0d57bb3419dbadee8fd92b48ba694.tar.bz2
pyramid-672f977604a0d57bb3419dbadee8fd92b48ba694.zip
- Document view registrations against classes and
``repoze.bfg.convention`` in context.
Diffstat (limited to 'docs/narr')
-rw-r--r--docs/narr/views.rst135
1 files changed, 115 insertions, 20 deletions
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index 36273de9d..6b9c92d0a 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -64,7 +64,7 @@ raise an error.
Mapping Views to URLs
----------------------
-You must associate a view with a URL by adding information to your
+You may associate a view with a URL by adding information to your
:term:`application registry` via :term:`ZCML` in your
``configure.zcml`` file using a ``bfg:view`` declaration.
@@ -72,26 +72,28 @@ You must associate a view with a URL by adding information to your
:linenos:
<bfg:view
- for=".models.IHello"
+ for=".models.Hello"
view=".views.hello_world"
name="hello.html"
/>
The above maps the ``.views.hello_world`` view function to
-:term:`context` objects which implement the ``.models.IHello``
-interface when the *view name* is ``hello.html``.
-
-Note that values prefixed with a period (``.``)for the ``for`` and
-``view`` attributes of a ``bfg:view`` (such as those above) mean
-"relative to the Python package directory in which this :term:`ZCML`
-file is stored". So if the above ``bfg:view`` declaration was made
-inside a ``configure.zcml`` file that lived in the ``hello`` package,
-you could replace the relative ``.models.IHello`` with the absolute
-``hello.models.IHello``; likewise you could replace the relative
-``.views.hello_world`` with the absolute ``hello.views.hello_world``.
-Either the relative or absolute form is functionally equivalent. It's
-often useful to use the relative form, in case your package's name
-changes. It's also shorter to type.
+:term:`context` objects which are instances of the Python class
+represented by ``.models.Hello`` when the *view name* is
+``hello.html``.
+
+.. note:: Values prefixed with a period (``.``)for the ``for`` and
+ ``view`` attributes of a ``bfg:view`` (such as those above) mean
+ "relative to the Python package directory in which this
+ :term:`ZCML` file is stored". So if the above ``bfg:view``
+ declaration was made inside a ``configure.zcml`` file that lived in
+ the ``hello`` package, you could replace the relative
+ ``.models.Hello`` with the absolute ``hello.models.Hello``;
+ likewise you could replace the relative ``.views.hello_world`` with
+ the absolute ``hello.views.hello_world``. Either the relative or
+ absolute form is functionally equivalent. It's often useful to use
+ the relative form, in case your package's name changes. It's also
+ shorter to type.
You can also declare a *default view* for a model type:
@@ -99,7 +101,7 @@ You can also declare a *default view* for a model type:
:linenos:
<bfg:view
- for=".models.IHello"
+ for=".models.Hello"
view=".views.hello_world"
/>
@@ -123,6 +125,98 @@ This indicates that when :mod:`repoze.bfg` identifies that the *view
name* is ``hello.html`` against *any* :term:`context`, this view will
be called.
+.. note::
+
+ If you're allergic to reading and writing :term:`ZCML`, or you're
+ just more comfortable defining your view declarations using Python,
+ you may use the :term:`repoze.bfg.convention` package. This
+ package provides a decorator named ``bfg_view`` that can be used to
+ associate ``for``, ``name``, ``permission`` and ``request_type``
+ information with a function that acts as a BFG view instead of
+ needing to rely on ZCML for the same task. You only need to add a
+ single ZCML stanza to your ``configure.zcml`` for
+ :term:`repoze.bfg.convention` to find all views decorated in this
+ fashion.
+
+Using Model Interfaces
+----------------------
+
+Instead of registering your views ``for`` a Python *class*, you can
+instead register a view for an :term:`interface`. Since an interface
+can be attached arbitrarily to any instance (as opposed to its
+identity being implied by only its class), associating a view with an
+interface can provide more flexibility for sharing a single view
+between two or more different implementations of a model type. For
+example, if two model object instances of different Python class types
+share the same interface, you can use the same view against each of
+them.
+
+In order to make use of interfaces in your application during view
+dispatch, you must create an interface and mark up your classes or
+instances with interface declarations that refer to this interface.
+
+To attach an interface to a *class*, you define the interface and use
+the ``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 an *instance*, you define the interface and
+use the ``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 an instance or
+class, the resulting ZCML to associate that interface with a view 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
+``.views.hello_world`` view with models that implement (aka provide)
+this interface.
+
+.. code-block:: xml
+ :linenos:
+
+ <bfg:view
+ for=".models.IHello"
+ view=".views.hello_world"
+ name="hello.html"
+ />
+
+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 ``.views.hello_world`` view will be invoked.
+
+See :term:`Interface` in the glossary to find more information about
+interfaces.
+
The ``bfg:view`` ZCML Element
-----------------------------
@@ -134,9 +228,10 @@ view
for
- A Python dotted-path name representing the :term:`interface` that
- the :term:`context` must have in order for this view to be found and
- called.
+ A Python dotted-path name representing the 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.
name