diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-07-02 10:06:34 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-07-02 10:06:34 +0000 |
| commit | e6855bbd24a006e729bacc343660e3001cae3919 (patch) | |
| tree | 85649d475b693cbd3ae4cb5e435b69f0fed68e5d /docs/narr/extending.rst | |
| parent | 2b804317d0470d1417996bd1b0a40a4d115b3721 (diff) | |
| download | pyramid-e6855bbd24a006e729bacc343660e3001cae3919.tar.gz pyramid-e6855bbd24a006e729bacc343660e3001cae3919.tar.bz2 pyramid-e6855bbd24a006e729bacc343660e3001cae3919.zip | |
- Added an "Extending" chapter to the narrative documentation which
explains how to extend or modify an existing BFG application using
another Python package and ZCML.
Diffstat (limited to 'docs/narr/extending.rst')
| -rw-r--r-- | docs/narr/extending.rst | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst new file mode 100644 index 000000000..06883031b --- /dev/null +++ b/docs/narr/extending.rst @@ -0,0 +1,112 @@ +.. _extending_chapter: + +Extending An Existing :mod:`repoze.bfg` Application +=================================================== + +If the developer of a :mod:`repoze.bfg` has obeyed certain constraints +while building the application, a third party should be able to change +the behavior of that application without touching the actual source +code that makes up the application. The behavior of a +:mod:`repoze.bfg` application that obeys these constraints can be +*extended* or *changed* without modification. + +Rules for Building An Extensible Application +-------------------------------------------- + +There's only one rule you need to obey if you want to build an +application that is extensible using :mod:`repoze.bfg`: you must not +use the ``@bfg_view`` decorator (or any other decorator meant to be +detected via the ZCML ``<scan>`` directive) to associate a view with a +context. Instead, you must use :term:`ZCML` for this +purpose. :term:`ZCML` statements that belong to an application can be +"overridden" by integrators as necessary, but decorators cannot. + +If you've inherited a :mod:`repoze.bfg` application that you'd like to +extend, but which *does* use ``@bfg_view`` decorators, you'll (at +least) need to change the source code of the original application, +moving the view declarations out of the decorators and into +:term:`ZCML`. Once this is done, you should be able to extend or +modify the application like any other. + +It's also often helpful for third party application "extenders" (aka +"integrators") if you break your ZCML into separate files which do +very specific things, and include them in the application's main +``configure.zcml`` via ``<include file="otherfile.zcml"/>`` +statements. This way, an integrator can avoid including any ZCML he +does not want by including only the ZCML files which contain the +registrations he needs. + +Extending an Existing Application +--------------------------------- + +To extend or change the behavior of an existing application, the only +hard-and-fast rule is that you need to write some :term:`ZCML`, and +perhaps some implementations of the types of things you'd like to +override (such as views), which is referred to within that ZCML. + +The general pattern for extending an application looks something like this: + +- Create a new Python package. The easiest way to do this is to + create a new :mod:`repoze.bfg` application using the "paster" + template mechanism. See :ref:`creating_a_project` for more + information. + +- Install the new package into the same Python environment as the + original application (e.g. ``python setup.py develop`` or ``python + setup.py install``). + +- Change the ``configure.zcml`` in the new package to the original + :mod:`repoze.bfg` application's ``configure.zcml`` via an include + statement, e.g. ``<include package="theoriginalapplication"/>``. + +- On a line in the new package's ``configure.zcml`` file that falls + after (XML-ordering-wise) the ``include`` of the original package, + put an ``includeOverride`` statement that includes another ZCML file + within the new package (for example ``<includeOverride + file="overrides.zcml"/>``. + +- Create an ``overrides.zcml`` file within the new package. The + statements in the ``overrides.zcml`` file will override any ZCML + statements made within the original application (such as views). + +- Create Python files containing views (and other overridden elements, + such as templates) as necessary, and wire these up, either extending + or overriding the original view registrations from the base + application within the ``overrides.zcml`` file. The ZCML ``<view>`` + statements you make which *modify* behavior will usually have the + same ``for`` and ``name`` (and ``request_type`` if used) as the + original, and will be in a form like:: + + <view for="theoriginalapplication.models.SomeModel" + name="theview" + view=".views.a_view_that_does_something_slightly_different" + /> + + Views which modify the behavior of an application will usually be + cutnpaste jobs from the original application with slight tweaks. + + A similar pattern can be used to extend the application. Just + register a new view against some existing model type. + +- Change the Paste ``.ini`` file that starts up the original + application. Add a ``configure_zcml`` statement within the + application's section in the file which points at your *new* + package's ``configure.zcml`` file. See :ref:`environment_chapter` + for more information about this setting. + +Dealing With ZCML Inclusions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes it's possible to include only certain ZCML files from an +application that contain only the registrations you really need, +omitting others. But sometimes it's not. For brute force purposes, +when you're getting ``view`` or ``route`` registrations that you don't +actually want in your overridden application, it's always appropriate +to just *not include* any ZCML file from the overridden application. +Instead, just cut and paste the entire contents of the +``configure.zcml`` (and any ZCML file included by the overridden +application's ``configure.zcml``) into your own package and omit the +``<include package=""/>`` ZCML statement in the overriding package's +``configure.zcml``. + + |
