summaryrefslogtreecommitdiff
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
parent38b6635fd101e51717d2daf7cc35f09590536cda (diff)
downloadpyramid-672f977604a0d57bb3419dbadee8fd92b48ba694.tar.gz
pyramid-672f977604a0d57bb3419dbadee8fd92b48ba694.tar.bz2
pyramid-672f977604a0d57bb3419dbadee8fd92b48ba694.zip
- Document view registrations against classes and
``repoze.bfg.convention`` in context.
-rw-r--r--CHANGES.txt3
-rw-r--r--docs/glossary.rst10
-rw-r--r--docs/narr/views.rst135
-rw-r--r--setup.py1
4 files changed, 126 insertions, 23 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 7fcdac7ba..00cf8673f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -3,6 +3,9 @@ Next release
- Change paster template ``tests.py`` to include a true unit test.
Retain old test as an integration test. Update documentation.
+ - Document view registrations against classes and
+ ``repoze.bfg.convention`` in context.
+
0.4.8 (11/12/2008)
Backwards Incompatibilities
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 0bd30edeb..92286dfb1 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -85,8 +85,6 @@ Glossary
Template
A file with replaceable parts that is capable of representing some
text, XML, or HTML when rendered.
- Interface
- An attribute of an object that determines its type.
Location
The path to an object in a model graph. See :ref:`location_aware`
for more information about how to make a model object *location-aware*.
@@ -245,7 +243,8 @@ Glossary
:mod:`repoze.bfg` is to perform view mappings via the ``bfg:view``
declaration. The ``configure.zcml`` file in a :mod:`repoze.bfg`
application represents the application's :term:`application
- registry`.
+ registry`. See :term:`repoze.bfg.convention` for an alternative
+ to ZCML for application configuration.
ReStructuredText
A `plain text format <http://docutils.sourceforge.net/rst.html>`_
that is the defacto standard for descriptive text shipped in
@@ -317,3 +316,8 @@ Glossary
`Barebones workflow for Python apps
<http://svn.repoze.org/repoze.workflow>`_ . It can be used by
:mod:`repoze.bfg` to form a workflow system.
+ repoze.bfg.convention
+ `An add-on for repoze.bfg
+ <http://svn.repoze.org/repoze.bfg/trunk>`_ which provides
+ alternative mechanisms for common :mod:`repoze.bfg` application
+ configuration tasks. Useful for the :term:`ZCML` -allergic.
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
diff --git a/setup.py b/setup.py
index 4d574aeb5..a2d3b11c5 100644
--- a/setup.py
+++ b/setup.py
@@ -38,6 +38,7 @@ install_requires=[
'zope.hookable',
'zope.interface',
'zope.proxy',
+ 'zope.testing',
]
setup(name='repoze.bfg',