summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/index.rst1
-rw-r--r--docs/latexindex.rst1
-rw-r--r--docs/narr/configuration.rst317
-rw-r--r--docs/narr/declarative.rst852
-rw-r--r--docs/narr/extending.rst10
-rw-r--r--docs/narr/firstapp.rst291
-rw-r--r--docs/narr/hybrid.rst314
-rw-r--r--docs/narr/project.rst21
-rw-r--r--docs/narr/security.rst211
-rw-r--r--docs/narr/startup.rst31
-rw-r--r--docs/narr/static.rst272
-rw-r--r--docs/narr/urldispatch.rst302
12 files changed, 1276 insertions, 1347 deletions
diff --git a/docs/index.rst b/docs/index.rst
index 79440448b..5a9aab565 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -51,6 +51,7 @@ Narrative documentation in chapter form explaining how to use
narr/environment
narr/unittesting
narr/hooks
+ narr/declarative
narr/extending
narr/resources
narr/router
diff --git a/docs/latexindex.rst b/docs/latexindex.rst
index 52eb8bd96..93d98d14c 100644
--- a/docs/latexindex.rst
+++ b/docs/latexindex.rst
@@ -50,6 +50,7 @@ Narrative Documentation
narr/environment
narr/unittesting
narr/hooks
+ narr/declarative
narr/extending
narr/resources
narr/router
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst
index cbc49d94b..82d0c8dda 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -6,30 +6,30 @@
Application Configuration
=========================
-Each deployment of an application written using :mod:`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. :mod:`pyramid` refers to the way
-in which code is plugged in to it for a specific application as
-"configuration".
-
-Most people understand "configuration" as coarse settings that inform
-the high-level operation of a specific application deployment. For
-instance, it's easy to think of the values implied by a ``.ini`` file
-parsed at application startup time as "configuration".
-:mod:`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 :mod:`pyramid` framework, you are "configuring"
-:mod:`pyramid` for the purpose of creating a particular application
-deployment.
-
-There are two different mechanisms you may use to configure
-:mod:`pyramid` to create an application: *imperative* configuration
-and *declarative* configuration. We'll examine both modes in the
-sections which follow.
+Each deployment of an application written using :mod:`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. :mod:`pyramid`
+refers to the way in which code is plugged in to it for a specific
+application as "configuration".
+
+Most people understand "configuration" as coarse settings that inform the
+high-level operation of a specific application deployment. For instance,
+it's easy to think of the values implied by a ``.ini`` file parsed at
+application startup time as "configuration". :mod:`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 :mod:`pyramid` framework, you are
+"configuring" :mod:`pyramid` for the purpose of creating a particular
+application deployment.
+
+There are two different mechanisms you may use to configure :mod:`pyramid` to
+create an application: *imperative* configuration and *declarative*
+configuration. We'll be using primarily the *imperative* configuration
+method in this book, for the sake of brevity and simplicity. For information
+about how to define application configuration declaratively, see
+:ref:`declarative_chapter`.
.. index::
single: imperative configuration
@@ -39,13 +39,6 @@ sections which follow.
Imperative Configuration
------------------------
-Experienced Python programmers might find that performing
-configuration "imperatively" fits their brain best. This is the
-configuration mode in which a developer cedes the least amount of
-control to the framework; it's "imperative" because you express the
-configuration directly in Python code, and you have the full power of
-Python at your disposal as you issue configuration statements.
-
Here's one of the simplest :mod:`pyramid` applications, configured
imperatively:
@@ -77,201 +70,22 @@ power of Python, including conditionals, can be employed in this mode
of configuration.
.. index::
- single: declarative configuration
-
-.. _declarative_configuration:
-
-Declarative Configuration
--------------------------
-
-A :mod:`pyramid` application can be alternately be configured
-"declaratively", if so desired. Declarative configuration relies on
-*declarations* made external to the code in a configuration file
-format named :term:`ZCML` (Zope Configuration Markup Language), an XML
-dialect.
-
-A :mod:`pyramid` application configured declaratively requires not
-one, but two files: a Python file and a :term:`ZCML` file.
-
-In a file named ``helloworld.py``:
-
-.. code-block:: python
- :linenos:
-
- from paste.httpserver import serve
- from pyramid.response import Response
- from pyramid.configuration import Configurator
-
- def hello_world(request):
- return Response('Hello world!')
-
- if __name__ == '__main__':
- config = Configurator()
- config.begin()
- config.load_zcml('configure.zcml')
- config.end()
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-In a file named ``configure.zcml`` in the same directory as the
-previously created ``helloworld.py``:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- </configure>
-
-This pair of files forms an application functionally equivalent to the
-application we created earlier in :ref:`imperative_configuration`.
-Let's examine the differences between that code listing and the code
-above.
-
-In :ref:`imperative_configuration`, we had the following lines within
-the ``if __name__ == '__main__'`` section of ``helloworld.py``:
-
-.. code-block:: python
- :linenos:
-
- if __name__ == '__main__':
- config = Configurator()
- config.begin()
- config.add_view(hello_world)
- config.end()
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-In our "declarative" code, we've removed the call to ``add_view`` and
-replaced it with a call to the
-:meth:`pyramid.configuration.Configurator.load_zcml` method so that
-it now reads as:
-
-.. code-block:: python
- :linenos:
-
- if __name__ == '__main__':
- config = Configurator()
- config.begin()
- config.load_zcml('configure.zcml')
- config.end()
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-Everything else is much the same.
-
-The ``config.load_zcml('configure.zcml')`` line tells the configurator
-to load configuration declarations from the file named
-``configure.zcml`` which sits next to ``helloworld.py`` on the
-filesystem. Let's take a look at that ``configure.zcml`` file again:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- </configure>
-
-Note that this file contains some XML, and that the XML contains a
-``<view>`` :term:`configuration declaration` tag that references a
-:term:`dotted Python name`. This dotted name refers to the
-``hello_world`` function that lives in our ``helloworld`` Python
-module.
-
-This ``<view>`` declaration tag performs the same function as the
-``add_view`` method that was employed within
-:ref:`imperative_configuration`. In fact, the ``<view>`` tag is
-effectively a "macro" which calls the
-:meth:`pyramid.configuration.Configurator.add_view` method on your
-behalf.
-
-The ``<view>`` tag is an example of a :mod:`pyramid` declaration
-tag. Other such tags include ``<route>`` and ``<scan>``. Each of
-these tags is effectively a "macro" which calls methods of a
-:class:`pyramid.configuration.Configurator` object on your behalf.
-
-Essentially, using a :term:`ZCML` file and loading it from the
-filesystem allows us to put our configuration statements within this
-XML file rather as declarations, rather than representing them as
-method calls to a :term:`Configurator` object. Otherwise, declarative
-and imperative configuration are functionally equivalent.
-
-Using declarative configuration has a number of benefits, the primary
-benefit being that applications configured declaratively can be
-*overridden* and *extended* by third parties without requiring the
-third party to change application code. If you want to build a
-framework or an extensible application, using declarative
-configuration is a good idea.
-
-Declarative configuration has an obvious downside: you can't use
-plain-old-Python syntax you probably already know and understand to
-configure your application; instead you need to use :term:`ZCML`.
-
-.. index::
- single: ZCML conflict detection
-
-ZCML Conflict Detection
-~~~~~~~~~~~~~~~~~~~~~~~
-
-A minor additional feature of ZCML is *conflict detection*. If you
-define two declaration tags within the same ZCML file which logically
-"collide", an exception will be raised, and the application will not
-start. For example, the following ZCML file has two conflicting
-``<view>`` tags:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- view="helloworld.hello_world"
- />
-
- </configure>
-
-If you try to use this ZCML file as the source of ZCML for an
-application, an error will be raised when you attempt to start the
-application. This error will contain information about which tags
-might have conflicted.
-
-.. index::
single: view_config
- single: ZCML view directive
single: configuration decoration
single: code scanning
.. _decorations_and_code_scanning:
Configuration Decorations and Code Scanning
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-An alternate mode of declarative configuration lends more *locality of
-reference* to a :term:`configuration declaration`. It's sometimes
-painful to have all configuration done in ZCML, or even in imperative
-code, because you may need to have two files open at once to see the
-"big picture": the file that represents the configuration, and the
-file that contains the implementation objects referenced by the
-configuration. To avoid this, :mod:`pyramid` allows you to insert
-:term:`configuration decoration` statements very close to code that is
+-------------------------------------------
+
+An alternate mode of configuration lends more *locality of reference* to a
+:term:`configuration declaration`. It's sometimes painful to have all
+configuration done in imperative code, because you may need to have two files
+open at once to see the "big picture": the file that represents the
+configuration, and the file that contains the implementation objects
+referenced by the configuration. To avoid this, :mod:`pyramid` allows you to
+insert :term:`configuration decoration` statements very close to code that is
referred to by the declaration itself. For example:
.. code-block:: python
@@ -322,46 +136,6 @@ and its subpackages. For example:
app = config.make_wsgi_app()
serve(app, host='0.0.0.0')
-:term:`ZCML` can also invoke a :term:`scan` via its ``<scan>``
-directive. If a ZCML file is processed that contains a scan
-directive, the package the ZCML file points to is scanned.
-
-.. topic:: Declaratively Starting a Scan
-
- .. code-block:: python
- :linenos:
-
- # helloworld.py
-
- from paste.httpserver import serve
- from pyramid.response import Response
- from pyramid.view import view_config
-
- @view_config()
- def hello(request):
- return Response('Hello')
-
- if __name__ == '__main__':
- from pyramid.configuration import Configurator
- config = Configurator()
- config.begin()
- config.load_zcml('configure.zcml')
- config.end()
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
- .. code-block:: xml
- :linenos:
-
- <configure xmlns="http://namespaces.repoze.org">
-
- <!-- configure.zcml -->
-
- <include package="pyramid.includes"/>
- <scan package="."/>
-
- </configure>
-
The scanning machinery imports each module and subpackage in a package
or module recursively, looking for special attributes attached to
objects defined within a module. These special attributes are
@@ -384,20 +158,15 @@ method, effectively:
config.add_view(hello)
-Which Mode Should I Use?
-------------------------
-
-A combination of imperative configuration, declarative configuration
-via ZCML and scanning can be used to configure any application. They
-are not mutually exclusive.
+Declarative Configuration
+-------------------------
-The :mod:`pyramid` authors often recommend using mostly declarative
-configuration, because it's the more traditional form of configuration
-used in :mod:`pyramid` applications, it can be overridden and
-extended by third party deployers, and there are more examples for it
-"in the wild".
+A third mode of configuration can be employed when you create a
+:mod:`pyramid` application named *declarative configuration*. This mode uses
+:term:`ZCML` to represent configuration statements rather than Python. ZCML
+is often used when application extensibility is important. Most of the
+examples in the narrative portion of this documentation concentrate on
+imperative configuration rather than ZCML, but almost everything that can be
+configured imperatively can also be configured via ZCML. See
+:ref:`declarative_chapter` for more information about ZCML.
-However, imperative mode configuration can be simpler to understand,
-and the framework is not "opinionated" about the choice. This book
-presents examples in both styles, mostly interchangeably. You can
-choose the mode that best fits your brain as necessary.
diff --git a/docs/narr/declarative.rst b/docs/narr/declarative.rst
new file mode 100644
index 000000000..33fd89073
--- /dev/null
+++ b/docs/narr/declarative.rst
@@ -0,0 +1,852 @@
+.. _declarative_chapter:
+
+Declarative Configuration
+=========================
+
+The mode of configuration most comprehensively detailed by examples in
+narrative chapters in this book is "imperative" configuration. This is the
+configuration mode in which a developer cedes the least amount of control to
+the framework; it's "imperative" because you express the configuration
+directly in Python code, and you have the full power of Python at your
+disposal as you issue configuration statements. However, another mode of
+configuration exists within :mod:`pyramid`, which often provides better
+extensibility and configuration conflict detection.
+
+A complete listing of ZCML directives is available within
+:ref:`zcml_directives`. This chapter provides an overview of how you might
+get started with ZCML and highlights some common tasks performed when you use
+ZCML. You can get a better understanding of when it's appropriate to use
+ZCML from :ref:`extending_chapter`.
+
+.. index::
+ single: declarative configuration
+
+.. _declarative_configuration:
+
+Declarative Configuration
+-------------------------
+
+A :mod:`pyramid` application can be configured "declaratively", if so
+desired. Declarative configuration relies on *declarations* made external to
+the code in a configuration file format named :term:`ZCML` (Zope
+Configuration Markup Language), an XML dialect.
+
+A :mod:`pyramid` application configured declaratively requires not
+one, but two files: a Python file and a :term:`ZCML` file.
+
+In a file named ``helloworld.py``:
+
+.. code-block:: python
+ :linenos:
+
+ from paste.httpserver import serve
+ from pyramid.response import Response
+ from pyramid.configuration import Configurator
+
+ def hello_world(request):
+ return Response('Hello world!')
+
+ if __name__ == '__main__':
+ config = Configurator()
+ config.begin()
+ config.load_zcml('configure.zcml')
+ config.end()
+ app = config.make_wsgi_app()
+ serve(app, host='0.0.0.0')
+
+In a file named ``configure.zcml`` in the same directory as the
+previously created ``helloworld.py``:
+
+.. code-block:: xml
+ :linenos:
+
+ <configure xmlns="http://pylonshq.com/pyramid">
+
+ <include package="pyramid.includes" />
+
+ <view
+ view="helloworld.hello_world"
+ />
+
+ </configure>
+
+This pair of files forms an application functionally equivalent to the
+application we created earlier in :ref:`imperative_configuration`.
+Let's examine the differences between that code listing and the code
+above.
+
+In :ref:`imperative_configuration`, we had the following lines within
+the ``if __name__ == '__main__'`` section of ``helloworld.py``:
+
+.. code-block:: python
+ :linenos:
+
+ if __name__ == '__main__':
+ config = Configurator()
+ config.begin()
+ config.add_view(hello_world)
+ config.end()
+ app = config.make_wsgi_app()
+ serve(app, host='0.0.0.0')
+
+In our "declarative" code, we've removed the call to ``add_view`` and
+replaced it with a call to the
+:meth:`pyramid.configuration.Configurator.load_zcml` method so that
+it now reads as:
+
+.. code-block:: python
+ :linenos:
+
+ if __name__ == '__main__':
+ config = Configurator()
+ config.begin()
+ config.load_zcml('configure.zcml')
+ config.end()
+ app = config.make_wsgi_app()
+ serve(app, host='0.0.0.0')
+
+Everything else is much the same.
+
+The ``config.load_zcml('configure.zcml')`` line tells the configurator
+to load configuration declarations from the file named
+``configure.zcml`` which sits next to ``helloworld.py`` on the
+filesystem. Let's take a look at that ``configure.zcml`` file again:
+
+.. code-block:: xml
+ :linenos:
+
+ <configure xmlns="http://pylonshq.com/pyramid">
+
+ <include package="pyramid.includes" />
+
+ <view
+ view="helloworld.hello_world"
+ />
+
+ </configure>
+
+Note that this file contains some XML, and that the XML contains a
+``<view>`` :term:`configuration declaration` tag that references a
+:term:`dotted Python name`. This dotted name refers to the
+``hello_world`` function that lives in our ``helloworld`` Python
+module.
+
+This ``<view>`` declaration tag performs the same function as the
+``add_view`` method that was employed within
+:ref:`imperative_configuration`. In fact, the ``<view>`` tag is
+effectively a "macro" which calls the
+:meth:`pyramid.configuration.Configurator.add_view` method on your
+behalf.
+
+The ``<view>`` tag is an example of a :mod:`pyramid` declaration
+tag. Other such tags include ``<route>`` and ``<scan>``. Each of
+these tags is effectively a "macro" which calls methods of a
+:class:`pyramid.configuration.Configurator` object on your behalf.
+
+Essentially, using a :term:`ZCML` file and loading it from the
+filesystem allows us to put our configuration statements within this
+XML file rather as declarations, rather than representing them as
+method calls to a :term:`Configurator` object. Otherwise, declarative
+and imperative configuration are functionally equivalent.
+
+Using declarative configuration has a number of benefits, the primary
+benefit being that applications configured declaratively can be
+*overridden* and *extended* by third parties without requiring the
+third party to change application code. If you want to build a
+framework or an extensible application, using declarative
+configuration is a good idea.
+
+Declarative configuration has an obvious downside: you can't use
+plain-old-Python syntax you probably already know and understand to
+configure your application; instead you need to use :term:`ZCML`.
+
+.. index::
+ single: ZCML conflict detection
+
+ZCML Conflict Detection
+~~~~~~~~~~~~~~~~~~~~~~~
+
+A minor additional feature of ZCML is *conflict detection*. If you
+define two declaration tags within the same ZCML file which logically
+"collide", an exception will be raised, and the application will not
+start. For example, the following ZCML file has two conflicting
+``<view>`` tags:
+
+.. code-block:: xml
+ :linenos:
+
+ <configure xmlns="http://pylonshq.com/pyramid">
+
+ <include package="pyramid.includes" />
+
+ <view
+ view="helloworld.hello_world"
+ />
+
+ <view
+ view="helloworld.hello_world"
+ />
+
+ </configure>
+
+If you try to use this ZCML file as the source of ZCML for an
+application, an error will be raised when you attempt to start the
+application. This error will contain information about which tags
+might have conflicted.
+
+.. index::
+ single: helloworld (declarative)
+
+.. _helloworld_declarative:
+
+Hello World, Goodbye World (Declarative)
+----------------------------------------
+
+Another almost entirely equivalent mode of application configuration
+exists named *declarative* configuration. :mod:`pyramid` can be
+configured for the same "hello world" application "declaratively", if
+so desired.
+
+To do so, first, create a file named ``helloworld.py``:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.configuration import Configurator
+ from pyramid.response import Response
+ from paste.httpserver import serve
+
+ def hello_world(request):
+ return Response('Hello world!')
+
+ def goodbye_world(request):
+ return Response('Goodbye world!')
+
+ if __name__ == '__main__':
+ config = Configurator()
+ config.begin()
+ config.load_zcml('configure.zcml')
+ config.end()
+ app = config.make_wsgi_app()
+ serve(app, host='0.0.0.0')
+
+Then create a file named ``configure.zcml`` in the same directory as
+the previously created ``helloworld.py``:
+
+.. code-block:: xml
+ :linenos:
+
+ <configure xmlns="http://pylonshq.com/pyramid">
+
+ <include package="pyramid.includes" />
+
+ <view
+ view="helloworld.hello_world"
+ />
+
+ <view
+ name="goodbye"
+ view="helloworld.goodbye_world"
+ />
+
+ </configure>
+
+This pair of files forms an application functionally equivalent to the
+application we created earlier in :ref:`helloworld_imperative`. We can run
+it the same way.
+
+.. code-block:: bash
+
+ $ python helloworld.py
+ serving on 0.0.0.0:8080 view at http://127.0.0.1:8080
+
+Let's examine the differences between the code in that section and the code
+above. In :ref:`helloworld_imperative_appconfig`, we had the following lines
+within the ``if __name__ == '__main__'`` section of ``helloworld.py``:
+
+.. code-block:: python
+ :linenos:
+
+ if __name__ == '__main__':
+ config = Configurator()
+ config.begin()
+ config.add_view(hello_world)
+ config.add_view(goodbye_world, name='goodbye')
+ config.end()
+ app = config.make_wsgi_app()
+ serve(app, host='0.0.0.0')
+
+In our "declarative" code, we've added a call to the
+:meth:`pyramid.configuration.Configurator.load_zcml` method with
+the value ``configure.zcml``, and we've removed the lines which read
+``config.add_view(hello_world)`` and ``config.add_view(goodbye_world,
+name='goodbye')``, so that it now reads as:
+
+.. code-block:: python
+ :linenos:
+
+ if __name__ == '__main__':
+ config = Configurator()
+ config.begin()
+ config.load_zcml('configure.zcml')
+ config.end()
+ app = config.make_wsgi_app()
+ serve(app, host='0.0.0.0')
+
+Everything else is much the same.
+
+The ``config.load_zcml('configure.zcml')`` line tells the configurator
+to load configuration declarations from the ``configure.zcml`` file
+which sits next to ``helloworld.py``. Let's take a look at the
+``configure.zcml`` file now:
+
+.. code-block:: xml
+ :linenos:
+
+ <configure xmlns="http://pylonshq.com/pyramid">
+
+ <include package="pyramid.includes" />
+
+ <view
+ view="helloworld.hello_world"
+ />
+
+ <view
+ name="goodbye"
+ view="helloworld.goodbye_world"
+ />
+
+ </configure>
+
+We already understand what the view code does, because the application
+is functionally equivalent to the application described in
+:ref:`helloworld_imperative`, but use of :term:`ZCML` is new. Let's
+break that down tag-by-tag.
+
+The ``<configure>`` Tag
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``configure.zcml`` ZCML file contains this bit of XML:
+
+.. code-block:: xml
+ :linenos:
+
+ <configure xmlns="http://pylonshq.com/pyramid">
+
+ <!-- other directives -->
+
+ </configure>
+
+Because :term:`ZCML` is XML, and because XML requires a single root
+tag for each document, every ZCML file used by :mod:`pyramid` must
+contain a ``configure`` container directive, which acts as the root
+XML tag. It is a "container" directive because its only job is to
+contain other directives.
+
+See also :ref:`configure_directive` and :ref:`word_on_xml_namespaces`.
+
+The ``<include>`` Tag
+~~~~~~~~~~~~~~~~~~~~~
+
+The ``configure.zcml`` ZCML file contains this bit of XML within the
+``<configure>`` root tag:
+
+.. code-block:: xml
+
+ <include package="pyramid.includes" />
+
+This self-closing tag instructs :mod:`pyramid` to load a ZCML file
+from the Python package with the :term:`dotted Python name`
+``pyramid.includes``, as specified by its ``package`` attribute.
+This particular ``<include>`` declaration is required because it
+actually allows subsequent declaration tags (such as ``<view>``, which
+we'll see shortly) to be recognized. The ``<include>`` tag
+effectively just includes another ZCML file, causing its declarations
+to be executed. In this case, we want to load the declarations from
+the file named ``configure.zcml`` within the
+:mod:`pyramid.includes` Python package. We know we want to load
+the ``configure.zcml`` from this package because ``configure.zcml`` is
+the default value for another attribute of the ``<include>`` tag named
+``file``. We could have spelled the include tag more verbosely, but
+equivalently as:
+
+.. code-block:: xml
+ :linenos:
+
+ <include package="pyramid.includes"
+ file="configure.zcml"/>
+
+The ``<include>`` tag that includes the ZCML statements implied by the
+``configure.zcml`` file from the Python package named
+:mod:`pyramid.includes` is basically required to come before any
+other named declaration in an application's ``configure.zcml``. If it
+is not included, subsequent declaration tags will fail to be
+recognized, and the configuration system will generate an error at
+startup. However, the ``<include package="pyramid.includes"/>``
+tag needs to exist only in a "top-level" ZCML file, it needn't also
+exist in ZCML files *included by* a top-level ZCML file.
+
+See also :ref:`include_directive`.
+
+The ``<view>`` Tag
+~~~~~~~~~~~~~~~~~~
+
+The ``configure.zcml`` ZCML file contains these bits of XML *after* the
+``<include>`` tag, but *within* the ``<configure>`` root tag:
+
+.. code-block:: xml
+ :linenos:
+
+ <view
+ view="helloworld.hello_world"
+ />
+
+ <view
+ name="goodbye"
+ view="helloworld.goodbye_world"
+ />
+
+These ``<view>`` declaration tags direct :mod:`pyramid` to create
+two :term:`view configuration` registrations. The first ``<view>``
+tag has an attribute (the attribute is also named ``view``), which
+points at a :term:`dotted Python name`, referencing the
+``hello_world`` function defined within the ``helloworld`` package.
+The second ``<view>`` tag has a ``view`` attribute which points at a
+:term:`dotted Python name`, referencing the ``goodbye_world`` function
+defined within the ``helloworld`` package. The second ``<view>`` tag
+also has an attribute called ``name`` with a value of ``goodbye``.
+
+These effect of the ``<view>`` tag declarations we've put into our
+``configure.zcml`` is functionally equivalent to the effect of lines
+we've already seen in an imperatively-configured application. We're
+just spelling things differently, using XML instead of Python.
+
+In our previously defined application, in which we added view
+configurations imperatively, we saw this code:
+
+.. ignore-next-block
+.. code-block:: python
+ :linenos:
+
+ config.add_view(hello_world)
+ config.add_view(goodbye_world, name='goodbye')
+
+Each ``<view>`` declaration tag encountered in a ZCML file effectively
+invokes the :meth:`pyramid.configuration.Configurator.add_view`
+method on the behalf of the developer. Various attributes can be
+specified on the ``<view>`` tag which influence the :term:`view
+configuration` it creates.
+
+Since the relative ordering of calls to
+:meth:`pyramid.configuration.Configurator.add_view` doesn't matter
+(see the sidebar entitled *View Dispatch and Ordering* within
+:ref:`adding_configuration`), the relative order of ``<view>`` tags in
+ZCML doesn't matter either. The following ZCML orderings are
+completely equivalent:
+
+.. topic:: Hello Before Goodbye
+
+ .. code-block:: xml
+ :linenos:
+
+ <view
+ view="helloworld.hello_world"
+ />
+
+ <view
+ name="goodbye"
+ view="helloworld.goodbye_world"
+ />
+
+.. topic:: Goodbye Before Hello
+
+ .. code-block:: xml
+ :linenos:
+
+ <view
+ name="goodbye"
+ view="helloworld.goodbye_world"
+ />
+
+ <view
+ view="helloworld.hello_world"
+ />
+
+We've now configured a :mod:`pyramid` helloworld application
+declaratively. More information about this mode of configuration is
+available in :ref:`declarative_configuration` and within
+:ref:`zcml_reference`.
+
+Scanning
+--------
+
+:term:`ZCML` can also invoke a :term:`scan` via its ``<scan>``
+directive. If a ZCML file is processed that contains a scan
+directive, the package the ZCML file points to is scanned.
+
+.. topic:: Declaratively Starting a Scan
+
+ .. code-block:: python
+ :linenos:
+
+ # helloworld.py
+
+ from paste.httpserver import serve
+ from pyramid.response import Response
+ from pyramid.view import view_config
+
+ @view_config()
+ def hello(request):
+ return Response('Hello')
+
+ if __name__ == '__main__':
+ from pyramid.configuration import Configurator
+ config = Configurator()
+ config.begin()
+ config.load_zcml('configure.zcml')
+ config.end()
+ app = config.make_wsgi_app()
+ serve(app, host='0.0.0.0')
+
+ .. code-block:: xml
+ :linenos:
+
+ <configure xmlns="http://namespaces.repoze.org">
+
+ <!-- configure.zcml -->
+
+ <include package="pyramid.includes"/>
+ <scan package="."/>
+
+ </configure>
+
+Which Mode Should I Use?
+------------------------
+
+A combination of imperative configuration, declarative configuration
+via ZCML and scanning can be used to configure any application. They
+are not mutually exclusive.
+
+The :mod:`pyramid` authors often recommend using mostly declarative
+configuration, because it's the more traditional form of configuration
+used in :mod:`pyramid` applications, it can be overridden and
+extended by third party deployers, and there are more examples for it
+"in the wild".
+
+However, imperative mode configuration can be simpler to understand,
+and the framework is not "opinionated" about the choice. This book
+presents examples in both styles, mostly interchangeably. You can
+choose the mode that best fits your brain as necessary.
+
+.. index::
+ single: ZCML directive; route
+
+.. _zcml_route_configuration:
+
+Configuring a Route via ZCML
+----------------------------
+
+Instead of using the imperative
+:meth:`pyramid.configuration.Configurator.add_route` method to add a new
+route, you can alternately use :term:`ZCML`. :ref:`route_directive`
+statements in a :term:`ZCML` file used by your application is a sign that
+you're using :term:`URL dispatch`. For example, the following :term:`ZCML
+declaration` causes a route to be added to the application.
+
+.. code-block:: xml
+ :linenos:
+
+ <route
+ name="myroute"
+ pattern="/prefix/:one/:two"
+ view=".views.myview"
+ />
+
+.. note::
+
+ Values prefixed with a period (``.``) within the values of ZCML
+ attributes such as the ``view`` attribute of a ``route`` mean
+ "relative to the Python package directory in which this
+ :term:`ZCML` file is stored". So if the above ``route``
+ declaration was made inside a ``configure.zcml`` file that lived in
+ the ``hello`` package, you could replace the relative
+ ``.views.myview`` with the absolute ``hello.views.myview`` 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.
+
+The order that routes are evaluated when declarative configuration is used
+is the order that they appear relative to each other in the ZCML file.
+
+See :ref:`route_directive` for full ``route`` ZCML directive
+documentation.
+
+.. index::
+ triple: view; zcml; static resource
+
+.. _zcml_static_resources_section:
+
+Serving Static Resources Using ZCML
+------------------------------------
+
+Use of the ``static`` ZCML directive makes static files available at a name
+relative to the application root URL, e.g. ``/static``.
+
+Note that the ``path`` provided to the ``static`` ZCML directive may be a
+fully qualified :term:`resource specification`, a package-relative path, or
+an *absolute path*. The ``path`` with the value ``a/b/c/static`` of a
+``static`` directive in a ZCML file that resides in the "mypackage" package
+will resolve to a package-qualified resource such as
+``some_package:a/b/c/static``.
+
+Here's an example of a ``static`` ZCML directive that will serve files
+up under the ``/static`` URL from the ``/var/www/static`` directory of
+the computer which runs the :mod:`pyramid` application using an
+absolute path.
+
+.. code-block:: xml
+ :linenos:
+
+ <static
+ name="static"
+ path="/var/www/static"
+ />
+
+Here's an example of a ``static`` directive that will serve files up
+under the ``/static`` URL from the ``a/b/c/static`` directory of the
+Python package named ``some_package`` using a fully qualified
+:term:`resource specification`.
+
+.. code-block:: xml
+ :linenos:
+
+ <static
+ name="static"
+ path="some_package:a/b/c/static"
+ />
+
+Here's an example of a ``static`` directive that will serve files up
+under the ``/static`` URL from the ``static`` directory of the Python
+package in which the ``configure.zcml`` file lives using a
+package-relative path.
+
+.. code-block:: xml
+ :linenos:
+
+ <static
+ name="static"
+ path="static"
+ />
+
+Whether you use for ``path`` a fully qualified resource specification,
+an absolute path, or a package-relative path, When you place your
+static files on the filesystem in the directory represented as the
+``path`` of the directive, you will then be able to view the static
+files in this directory via a browser at URLs prefixed with the
+directive's ``name``. For instance if the ``static`` directive's
+``name`` is ``static`` and the static directive's ``path`` is
+``/path/to/static``, ``http://localhost:6543/static/foo.js`` will
+return the file ``/path/to/static/dir/foo.js``. The static directory
+may contain subdirectories recursively, and any subdirectories may
+hold files; these will be resolved by the static view as you would
+expect.
+
+While the ``path`` argument can be a number of different things, the
+``name`` argument of the ``static`` ZCML directive can also be one of
+a number of things: a *view name* or a *URL*. The above examples have
+shown usage of the ``name`` argument as a view name. When ``name`` is
+a *URL* (or any string with a slash (``/``) in it), static resources
+can be served from an external webserver. In this mode, the ``name``
+is used as the URL prefix when generating a URL using
+:func:`pyramid.url.static_url`.
+
+For example, the ``static`` ZCML directive may be fed a ``name``
+argument which is ``http://example.com/images``:
+
+.. code-block:: xml
+ :linenos:
+
+ <static
+ name="http://example.com/images"
+ path="mypackage:images"
+ />
+
+Because the ``static`` ZCML directive is 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.url.static_url` will generate a URL
+something like ``http://example.com/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.
+
+The :meth:`pyramid.configuration.Configurator.add_static_view` method offers
+an imperative equivalent to the ``static`` ZCML directive. Use of the
+``add_static_view`` imperative configuration method is completely equivalent
+to using ZCML for the same purpose. See :ref:`static_resources_section` for
+more information.
+
+.. _zcml_authorization_policy:
+
+Enabling an Authorization Policy Via ZCML
+-----------------------------------------
+
+If you'd rather use :term:`ZCML` to specify an authorization policy
+than imperative configuration, modify the ZCML file loaded by your
+application (usually named ``configure.zcml``) to enable an
+authorization policy.
+
+For example, to enable a policy which compares the value of an "auth
+ticket" cookie passed in the request's environment which contains a
+reference to a single :term:`principal` against the principals present
+in any :term:`ACL` found in model data when attempting to call some
+:term:`view`, modify your ``configure.zcml`` to look something like
+this:
+
+.. code-block:: xml
+ :linenos:
+
+ <configure xmlns="http://pylonshq.com/pyramid">
+
+ <!-- views and other directives before this... -->
+
+ <authtktauthenticationpolicy
+ secret="iamsosecret"/>
+
+ <aclauthorizationpolicy/>
+
+ </configure>
+
+"Under the hood", these statements cause an instance of the class
+:class:`pyramid.authentication.AuthTktAuthenticationPolicy` to be
+injected as the :term:`authentication policy` used by this application
+and an instance of the class
+:class:`pyramid.authorization.ACLAuthorizationPolicy` to be
+injected as the :term:`authorization policy` used by this application.
+
+:mod:`pyramid` ships with a number of authorization and
+authentication policy ZCML directives that should prove useful. See
+:ref:`authentication_policies_directives_section` and
+:ref:`authorization_policies_directives_section` for more information.
+
+.. index::
+ pair: ZCML directive; authentication policy
+
+.. _authentication_policies_directives_section:
+
+Built-In Authentication Policy ZCML Directives
+----------------------------------------------
+
+Instead of configuring an authentication policy and authorization
+policy imperatively, :mod:`pyramid` ships with a few "pre-chewed"
+authentication policy ZCML directives that you can make use of within
+your application.
+
+``authtktauthenticationpolicy``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When this directive is used, authentication information is obtained
+from an "auth ticket" cookie value, assumed to be set by a custom
+login form.
+
+An example of its usage, with all attributes fully expanded:
+
+.. code-block:: xml
+ :linenos:
+
+ <authtktauthenticationpolicy
+ secret="goshiamsosecret"
+ callback=".somemodule.somefunc"
+ cookie_name="mycookiename"
+ secure="false"
+ include_ip="false"
+ timeout="86400"
+ reissue_time="600"
+ max_age="31536000"
+ path="/"
+ http_only="false"
+ />
+
+See :ref:`authtktauthenticationpolicy_directive` for details about
+this directive.
+
+``remoteuserauthenticationpolicy``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When this directive is used, authentication information is obtained
+from a ``REMOTE_USER`` key in the WSGI environment, assumed to
+be set by a WSGI server or an upstream middleware component.
+
+An example of its usage, with all attributes fully expanded:
+
+.. code-block:: xml
+ :linenos:
+
+ <remoteuserauthenticationpolicy
+ environ_key="REMOTE_USER"
+ callback=".somemodule.somefunc"
+ />
+
+See :ref:`remoteuserauthenticationpolicy_directive` for detailed
+information.
+
+``repozewho1authenticationpolicy``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When this directive is used, authentication information is obtained
+from a ``repoze.who.identity`` key in the WSGI environment, assumed to
+be set by :term:`repoze.who` middleware.
+
+An example of its usage, with all attributes fully expanded:
+
+.. code-block:: xml
+ :linenos:
+
+ <repozewho1authenticationpolicy
+ identifier_name="auth_tkt"
+ callback=".somemodule.somefunc"
+ />
+
+See :ref:`repozewho1authenticationpolicy_directive` for detailed
+information.
+
+.. index::
+ pair: ZCML directive; authorization policy
+
+.. _authorization_policies_directives_section:
+
+Built-In Authorization Policy ZCML Directives
+---------------------------------------------
+
+``aclauthorizationpolicy``
+
+When this directive is used, authorization information is obtained
+from :term:`ACL` objects attached to model instances.
+
+An example of its usage, with all attributes fully expanded:
+
+.. code-block:: xml
+ :linenos:
+
+ <aclauthorizationpolicy/>
+
+In other words, it has no configuration attributes; its existence in a
+``configure.zcml`` file enables it.
+
+See :ref:`aclauthorizationpolicy_directive` for detailed information.
+
+.. Todo
+.. ----
+
+.. - ``narr/project.rst`` chapter describes execution of a paster template that
+.. is based on XML.
+
+.. - Skipped views chapter.
+
+.. - i18n chapter still has topics for ZCML
+
+.. - events chapter still has topics for ZCML
+
+.. - hooks chapter still has topics for ZCML
+
+.. - resources chapter still has topics for ZCML
diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst
index 88b42eabf..ac482895b 100644
--- a/docs/narr/extending.rst
+++ b/docs/narr/extending.rst
@@ -26,11 +26,11 @@ application through methods of the :term:`Configurator` (except for
the :meth:`pyramid.configuration.Configurator.load_zcml` method).
Instead, you must always use :term:`ZCML` for the equivalent
-purposes. :term:`ZCML` declarations that belong to an application can
-be "overridden" by integrators as necessary, but decorators and
-imperative code which perform the same tasks cannot. Use only
-:term:`ZCML` to configure your application if you'd like it to be
-extensible.
+purposes. :term:`ZCML` declarations that belong to an application can be
+"overridden" by integrators as necessary, but decorators and imperative code
+which perform the same tasks cannot. Use only :term:`ZCML` to configure your
+application if you'd like it to be extensible. See
+:ref:`declarative_chapter` for information about using ZCML.
Fundamental Plugpoints
~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index 67dd6b8fb..9be087036 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -17,8 +17,8 @@ explain in more detail how the application works.
.. _helloworld_imperative:
-Hello World, Goodbye World (Imperative)
----------------------------------------
+Hello World, Goodbye World
+--------------------------
Here's one of the very simplest :mod:`pyramid` applications,
configured imperatively:
@@ -369,295 +369,14 @@ Our hello world application is one of the simplest possible
that it's configured imperatively because the full power of Python is
available to us as we perform configuration tasks.
-.. index::
- single: helloworld (declarative)
-
-.. _helloworld_declarative:
-
-Hello World, Goodbye World (Declarative)
-----------------------------------------
-
-Another almost entirely equivalent mode of application configuration
-exists named *declarative* configuration. :mod:`pyramid` can be
-configured for the same "hello world" application "declaratively", if
-so desired.
-
-To do so, first, create a file named ``helloworld.py``:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.configuration import Configurator
- from pyramid.response import Response
- from paste.httpserver import serve
-
- def hello_world(request):
- return Response('Hello world!')
-
- def goodbye_world(request):
- return Response('Goodbye world!')
-
- if __name__ == '__main__':
- config = Configurator()
- config.begin()
- config.load_zcml('configure.zcml')
- config.end()
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-Then create a file named ``configure.zcml`` in the same directory as
-the previously created ``helloworld.py``:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
- </configure>
-
-This pair of files forms an application functionally equivalent to the
-application we created earlier in :ref:`helloworld_imperative`. We can run
-it the same way.
-
-.. code-block:: bash
-
- $ python helloworld.py
- serving on 0.0.0.0:8080 view at http://127.0.0.1:8080
-
-Let's examine the differences between the code in that section and the code
-above. In :ref:`helloworld_imperative_appconfig`, we had the following lines
-within the ``if __name__ == '__main__'`` section of ``helloworld.py``:
-
-.. code-block:: python
- :linenos:
-
- if __name__ == '__main__':
- config = Configurator()
- config.begin()
- config.add_view(hello_world)
- config.add_view(goodbye_world, name='goodbye')
- config.end()
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-In our "declarative" code, we've added a call to the
-:meth:`pyramid.configuration.Configurator.load_zcml` method with
-the value ``configure.zcml``, and we've removed the lines which read
-``config.add_view(hello_world)`` and ``config.add_view(goodbye_world,
-name='goodbye')``, so that it now reads as:
-
-.. code-block:: python
- :linenos:
-
- if __name__ == '__main__':
- config = Configurator()
- config.begin()
- config.load_zcml('configure.zcml')
- config.end()
- app = config.make_wsgi_app()
- serve(app, host='0.0.0.0')
-
-Everything else is much the same.
-
-The ``config.load_zcml('configure.zcml')`` line tells the configurator
-to load configuration declarations from the ``configure.zcml`` file
-which sits next to ``helloworld.py``. Let's take a look at the
-``configure.zcml`` file now:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <include package="pyramid.includes" />
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
- </configure>
-
-We already understand what the view code does, because the application
-is functionally equivalent to the application described in
-:ref:`helloworld_imperative`, but use of :term:`ZCML` is new. Let's
-break that down tag-by-tag.
-
-The ``<configure>`` Tag
-~~~~~~~~~~~~~~~~~~~~~~~
-
-The ``configure.zcml`` ZCML file contains this bit of XML:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <!-- other directives -->
-
- </configure>
-
-Because :term:`ZCML` is XML, and because XML requires a single root
-tag for each document, every ZCML file used by :mod:`pyramid` must
-contain a ``configure`` container directive, which acts as the root
-XML tag. It is a "container" directive because its only job is to
-contain other directives.
-
-See also :ref:`configure_directive` and :ref:`word_on_xml_namespaces`.
-
-The ``<include>`` Tag
-~~~~~~~~~~~~~~~~~~~~~
-
-The ``configure.zcml`` ZCML file contains this bit of XML within the
-``<configure>`` root tag:
-
-.. code-block:: xml
-
- <include package="pyramid.includes" />
-
-This self-closing tag instructs :mod:`pyramid` to load a ZCML file
-from the Python package with the :term:`dotted Python name`
-``pyramid.includes``, as specified by its ``package`` attribute.
-This particular ``<include>`` declaration is required because it
-actually allows subsequent declaration tags (such as ``<view>``, which
-we'll see shortly) to be recognized. The ``<include>`` tag
-effectively just includes another ZCML file, causing its declarations
-to be executed. In this case, we want to load the declarations from
-the file named ``configure.zcml`` within the
-:mod:`pyramid.includes` Python package. We know we want to load
-the ``configure.zcml`` from this package because ``configure.zcml`` is
-the default value for another attribute of the ``<include>`` tag named
-``file``. We could have spelled the include tag more verbosely, but
-equivalently as:
-
-.. code-block:: xml
- :linenos:
-
- <include package="pyramid.includes"
- file="configure.zcml"/>
-
-The ``<include>`` tag that includes the ZCML statements implied by the
-``configure.zcml`` file from the Python package named
-:mod:`pyramid.includes` is basically required to come before any
-other named declaration in an application's ``configure.zcml``. If it
-is not included, subsequent declaration tags will fail to be
-recognized, and the configuration system will generate an error at
-startup. However, the ``<include package="pyramid.includes"/>``
-tag needs to exist only in a "top-level" ZCML file, it needn't also
-exist in ZCML files *included by* a top-level ZCML file.
-
-See also :ref:`include_directive`.
-
-The ``<view>`` Tag
-~~~~~~~~~~~~~~~~~~
-
-The ``configure.zcml`` ZCML file contains these bits of XML *after* the
-``<include>`` tag, but *within* the ``<configure>`` root tag:
-
-.. code-block:: xml
- :linenos:
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
-These ``<view>`` declaration tags direct :mod:`pyramid` to create
-two :term:`view configuration` registrations. The first ``<view>``
-tag has an attribute (the attribute is also named ``view``), which
-points at a :term:`dotted Python name`, referencing the
-``hello_world`` function defined within the ``helloworld`` package.
-The second ``<view>`` tag has a ``view`` attribute which points at a
-:term:`dotted Python name`, referencing the ``goodbye_world`` function
-defined within the ``helloworld`` package. The second ``<view>`` tag
-also has an attribute called ``name`` with a value of ``goodbye``.
-
-These effect of the ``<view>`` tag declarations we've put into our
-``configure.zcml`` is functionally equivalent to the effect of lines
-we've already seen in an imperatively-configured application. We're
-just spelling things differently, using XML instead of Python.
-
-In our previously defined application, in which we added view
-configurations imperatively, we saw this code:
-
-.. ignore-next-block
-.. code-block:: python
- :linenos:
-
- config.add_view(hello_world)
- config.add_view(goodbye_world, name='goodbye')
-
-Each ``<view>`` declaration tag encountered in a ZCML file effectively
-invokes the :meth:`pyramid.configuration.Configurator.add_view`
-method on the behalf of the developer. Various attributes can be
-specified on the ``<view>`` tag which influence the :term:`view
-configuration` it creates.
-
-Since the relative ordering of calls to
-:meth:`pyramid.configuration.Configurator.add_view` doesn't matter
-(see the sidebar entitled *View Dispatch and Ordering* within
-:ref:`adding_configuration`), the relative order of ``<view>`` tags in
-ZCML doesn't matter either. The following ZCML orderings are
-completely equivalent:
-
-.. topic:: Hello Before Goodbye
-
- .. code-block:: xml
- :linenos:
-
- <view
- view="helloworld.hello_world"
- />
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
-.. topic:: Goodbye Before Hello
-
- .. code-block:: xml
- :linenos:
-
- <view
- name="goodbye"
- view="helloworld.goodbye_world"
- />
-
- <view
- view="helloworld.hello_world"
- />
-
-We've now configured a :mod:`pyramid` helloworld application
-declaratively. More information about this mode of configuration is
-available in :ref:`declarative_configuration` and within
-:ref:`zcml_reference`.
+An example of using *declarative* configuration to perform the same task is
+available within :ref:`declarative_configuration`.
References
----------
For more information about the API of a :term:`Configurator` object,
-see :class:`pyramid.configuration.Configurator` . The equivalent
-ZCML declaration tags are introduced in :ref:`zcml_reference`.
+see :class:`pyramid.configuration.Configurator` .
For more information about :term:`view configuration`, see
:ref:`views_chapter`.
diff --git a/docs/narr/hybrid.rst b/docs/narr/hybrid.rst
index cdac3642a..24ae63059 100644
--- a/docs/narr/hybrid.rst
+++ b/docs/narr/hybrid.rst
@@ -33,33 +33,24 @@ in isolation before trying to combine them.
URL Dispatch Only
~~~~~~~~~~~~~~~~~
-An application that uses :term:`url dispatch` exclusively to map URLs
-to code will often have declarations like this within :term:`ZCML`:
+An application that uses :term:`url dispatch` exclusively to map URLs to code
+will often have statements like this within your application startup
+configuration:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern=":foo/:bar"
- name="foobar"
- view=".views.foobar"
- />
+ # config is an instance of pyramid.configuration.Configurator
- <route
- pattern=":baz/:buz"
- name="bazbuz"
- view=".views.bazbuz"
- />
+ config.add_route('foobar', ':foo/:bar', view='myproject.views.foobar')
+ config.add_route('bazbuz', ':baz/:buz', view='myproject.views.bazbuz')
Each :term:`route` typically corresponds to a single view callable,
and when that route is matched during a request, the view callable
named by the ``view`` attribute is invoked.
-Typically, an application that uses only URL dispatch won't perform
-any configuration in ZCML that includes a ``<view>`` declaration and
-won't have any calls to
-:meth:`pyramid.configuration.Configurator.add_view` in its startup
-code.
+Typically, an application that uses only URL dispatch won't perform any calls
+to :meth:`pyramid.configuration.Configurator.add_view` in its startup code.
Traversal Only
~~~~~~~~~~~~~~
@@ -67,28 +58,22 @@ Traversal Only
An application that uses only traversal will have view configuration
declarations that look like this:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <view
- name="foobar"
- view=".views.foobar"
- />
+ # config is an instance of pyramid.configuration.Configurator
- <view
- name="bazbuz"
- view=".views.bazbuz"
- />
+ config.add_view('mypackage.views.foobar', name='foobar')
+ config.add_view('mypackage.views.bazbuz', name='bazbuz')
When the above configuration is applied to an application, the
-``.views.foobar`` view callable above will be called when the URL
-``/foobar`` is visited. Likewise, the view ``.views.bazbuz`` will be
-called when the URL ``/bazbuz`` is visited.
+``mypackage.views.foobar`` view callable above will be called when the URL
+``/foobar`` is visited. Likewise, the view ``mypackage.views.bazbuz`` will
+be called when the URL ``/bazbuz`` is visited.
-An application that uses :term:`traversal` exclusively to map URLs to
-code usually won't have any ZCML ``<route>`` declarations nor will it
-make any calls to the
-:meth:`pyramid.configuration.Configurator.add_route` method.
+Typically, an application that uses traversal exclusively won't perform any
+calls to :meth:`pyramid.configuration.Configurator.add_route` in its startup
+code.
Hybrid Applications
-------------------
@@ -197,13 +182,10 @@ A hybrid application most often implies the inclusion of a route
configuration that contains the special token ``*traverse`` at the end
of a route's pattern:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern=":foo/:bar/*traverse"
- name="home"
- />
+ config.add_route('home', ':foo/:bar/*traverse')
A ``*traverse`` token at the end of the pattern in a route's
configuration implies a "remainder" *capture* value. When it is used,
@@ -215,13 +197,12 @@ remainder becomes the path used to perform traversal.
The ``*remainder`` route pattern syntax is explained in more
detail within :ref:`route_pattern_syntax`.
-Note that unlike the examples provided within
-:ref:`urldispatch_chapter`, the ``<route>`` configuration named
-previously does not name a ``view`` attribute. This is because a
-hybrid mode application relies on :term:`traversal` to do
-:term:`context finding` and :term:`view lookup` instead of invariably
-invoking a specific view callable named directly within the matched
-route's configuration.
+Note that unlike the examples provided within :ref:`urldispatch_chapter`, the
+``add_route`` configuration statement named previously does not pass a
+``view`` argument. This is because a hybrid mode application relies on
+:term:`traversal` to do :term:`context finding` and :term:`view lookup`
+instead of invariably invoking a specific view callable named directly within
+the matched route's configuration.
Because the pattern of the above route ends with ``*traverse``, when this
route configuration is matched during a request, :mod:`pyramid`
@@ -259,14 +240,11 @@ Above, we've defined a (bogus) graph here that can be traversed, and a
``root_factory`` function that can be used as part of a particular
route configuration statement:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern=":foo/:bar/*traverse"
- name="home"
- factory=".routes.root_factory"
- />
+ 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
@@ -315,32 +293,26 @@ but with a caveat: in order for view lookup to work, we need to define
a view configuration that will match when :term:`view lookup` is
invoked after a route matches:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern=":foo/:bar/*traverse"
- name="home"
- factory=".routes.root_factory"
- />
-
- <view
- route_name="home"
- view=".views.myview"
- />
+ config.add_route('home', ':foo/:bar/*traverse',
+ factory='mypackage.routes.root_factory')
+ config.add_view('mypackage.views.myview', route_name='home')
-Note that the above ``view`` declaration includes a ``route_name``
-argument. Views that include a ``route_name`` argument are meant to
-associate a particular view declaration with a route, using the
-route's name, in order to indicate that the view should *only be
-invoked when the route matches*.
+Note that the above call to
+:meth:`pyramid.configuration.Configurator.add_view` includes a ``route_name``
+argument. View configurations that include a ``route_name`` argument are
+meant to associate a particular view declaration with a route, using the
+route's name, in order to indicate that the view should *only be invoked when
+the route matches*.
-View configurations may have a ``route_name`` attribute which refers
-to the value of the ``<route>`` declaration's ``name`` attribute. In
-the above example, the route name is ``home``, referring to the name
-of the route defined above it.
+Calls to :meth:`pyramid.configuration.Configurator.add_view` may pass a
+``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.
-The above ``.views.myview`` view will be invoked when:
+The above ``mypackage.views.myview`` view callable will be invoked when:
- the route named "home" is matched
@@ -351,29 +323,18 @@ The above ``.views.myview`` view will be invoked when:
It is also possible to declare alternate views that may be invoked
when a hybrid route is matched:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern=":foo/:bar/*traverse"
- name="home"
- factory=".routes.root_factory"
- />
+ config.add_route('home', ':foo/:bar/*traverse',
+ factory='mypackage.routes.root_factory')
+ config.add_view('mypackage.views.myview', name='home')
+ config.add_view('mypackage.views.another_view', name='another',
+ route_name='home')
- <view
- route_name="home"
- view=".views.myview"
- />
-
- <view
- route_name="home"
- name="another"
- view=".views.another_view"
- />
-
-The ``view`` declaration for ``.views.another_view`` above names a
-different view and, more importantly, a different :term:`view name`.
-The above ``.views.another_view`` view will be invoked when:
+The ``add_view`` call for ``mypackage.views.another_view`` above names a
+different view and, more importantly, a different :term:`view name`. The
+above ``mypackage.views.another_view`` view will be invoked when:
- the route named "home" is matched
@@ -381,10 +342,10 @@ The above ``.views.another_view`` view will be invoked when:
- the :term:`context` is any object.
-For instance, if the URL ``http://example.com/one/two/a/another`` is
-provided to an application that uses the previously mentioned object
-graph, the ``.views.another`` view callable will be called instead of
-the ``.views.myview`` view callable because the :term:`view name` will
+For instance, if the URL ``http://example.com/one/two/a/another`` is provided
+to an application that uses the previously mentioned object graph, the
+``mypackage.views.another`` view callable will be called instead of the
+``mypackage.views.myview`` view callable because the :term:`view name` will
be ``another`` instead of the empty string.
More complicated matching can be composed. All arguments to *route*
@@ -397,26 +358,21 @@ Using the ``traverse`` Argument In a Route Definition
Rather than using the ``*traverse`` remainder marker in a pattern, you
can use the ``traverse`` argument to the
-:meth:`pyramid.configuration.Configurator.add_route`` method or the
-``traverse`` attribute of the :ref:`route_directive` ZCML directive.
-(either method is equivalent).
+:meth:`pyramid.configuration.Configurator.add_route`` method.
When you use the ``*traverse`` remainder marker, the traversal path is
limited to being the remainder segments of a request URL when a route
matches. However, when you use the ``traverse`` argument or
attribute, you have more control over how to compose a traversal path.
-Here's a use of the ``traverse`` pattern in a ZCML ``route``
-declaration:
+Here's a use of the ``traverse`` pattern in a call to
+:meth:`pyramid.configuration.Configurator.add_route`:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- name="abc"
- pattern="/articles/:article/edit"
- traverse="/articles/:article"
- />
+ config.add_route('abc', '/articles/:article/edit',
+ traverse='/articles/:article')
The syntax of the ``traverse`` argument is the same as it is for
``pattern``.
@@ -446,28 +402,20 @@ 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 ``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, 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.
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern="/abc/*traverse"
- name="abc"
- use_global_views="True"
- />
-
- <view
- name="bazbuz"
- view=".views.bazbuz"
- />
+ config.add_route('abc', '/abc/*traverse', use_global_views=True)
+ config.add_view('myproject.views.bazbuz', name='bazbuz')
.. index::
single: route subpath
@@ -491,18 +439,15 @@ but the traversal algorithm will return a :term:`subpath` list implied
by the capture value of ``*subpath``. You'll see this pattern most
commonly in route declarations that look like this:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern="/static/*subpath"
- name="static"
- view=".views.static_view"
- />
+ config.add_route('static', '/static/*subpath',
+ view='mypackage.views.static_view')
-Where ``.views.static_view`` is an instance of
-:class:`pyramid.view.static`. This effectively tells the static
-helper to traverse everything in the subpath as a filename.
+Where ``mypackage.views.static_view`` is an instance of
+:class:`pyramid.view.static`. This effectively tells the static helper to
+traverse everything in the subpath as a filename.
Corner Cases
------------
@@ -515,52 +460,35 @@ Registering a Default View for a Route That Has a ``view`` Attribute
It is an error to provide *both* a ``view`` argument to a :term:`route
configuration` *and* a :term:`view configuration` which names a
-``route_name`` that has no ``name`` value or the empty ``name`` value.
-For example, this pair of route/view ZCML declarations will generate a
-"conflict" error at startup time.
+``route_name`` that has no ``name`` value or the empty ``name`` value. For
+example, this pair of declarations will generate a "conflict" error at
+startup time.
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern=":foo/:bar/*traverse"
- name="home"
- view=".views.home"
- />
-
- <view
- route_name="home"
- view=".views.another"
- />
+ config.add_route('home', ':foo/:bar/*traverse',
+ view='myproject.views.home')
+ config.add_view('myproject.views.another', route_name='home')
-This is because the ``view`` attribute of the ``<route>`` statement
-above is an *implicit* default view when that route matches.
-``<route>`` declarations don't *need* to supply a view attribute. For
-example, this ``<route>`` statement:
+This is because the ``view`` argument to the
+:meth:`pyramid.configuration.Configurator.add_route` above is an *implicit*
+default view when that route matches. ``add_route`` calls don't *need* to
+supply a view attribute. For example, this ``add_route`` call:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern=":foo/:bar/*traverse"
- name="home"
- view=".views.home"
- />
+ config.add_route('home', ':foo/:bar/*traverse',
+ view='myproject.views.home')
Can also be spelled like so:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern=":foo/:bar/*traverse"
- name="home"
- />
-
- <view
- route_name="home"
- view=".views.home"
- />
+ config.add_route('home', ':foo/:bar/*traverse')
+ config.add_view('myproject.views.home', route_name='home')
The two spellings are logically equivalent. In fact, the former is
just a syntactical shortcut for the latter.
@@ -570,42 +498,26 @@ Binding Extra Views Against a Route Configuration that Doesn't Have a ``*travers
Here's another corner case that just makes no sense.
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern="/abc"
- name="abc"
- view=".views.abc"
- />
+ config.add_route('abc', '/abc', view='myproject.views.abc')
+ config.add_view('myproject.views.bazbuz', name='bazbuz',
+ route_name='abc')
- <view
- name="bazbuz"
- view=".views.bazbuz"
- route_name="abc"
- />
+The above view declaration is useless, because it will never be matched when
+the route it references has matched. Only the view associated with the route
+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.
-The above ``<view>`` declaration is useless, because it will never be
-matched when the route it references has matched. Only the view
-associated with the route itself (``.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``
+token must end the route's pattern. For example:
-To make the above ``<view>`` declaration non-useless, the special
-``*traverse`` token must end the route's pattern. For example:
-
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- pattern="/abc/*traverse"
- name="abc"
- view=".views.abc"
- />
-
- <view
- name="bazbuz"
- view=".views.bazbuz"
- route_name="abc"
- />
+ config.add_route('abc', '/abc/*traverse', view='myproject.views.abc')
+ config.add_view('myproject.views.bazbuz', name='bazbuz',
+ route_name='abc')
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 506d1a623..471ae8754 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -67,14 +67,19 @@ The included templates are these:
URL mapping via :term:`URL dispatch` and Pylons-style view handlers,
some extra functionality, and SQLAlchemy set up.
-Each of these project templates uses :term:`ZCML` instead of
-:term:`imperative configuration`. Each also makes the assumption that
-you want your code to live in a Python :term:`package`. Even if your
-application is extremely simple, it is useful to place code that
-drives the application within a package, because a package is more
-easily extended with new code. An application that lives inside a
-package can also be distributed more easily than one which does not
-live within a package.
+The project templates which start with ``pyramid_`` uses :term:`ZCML` (see
+:ref:`declarative_chapter`) instead of :term:`imperative configuration`.
+
+The project templates which start with ``pylons_`` use imperative
+configuration (the type of configuration which we've been showing so far in
+the book).
+
+Each also makes the assumption that you want your code to live in a Python
+:term:`package`. Even if your application is extremely simple, it is useful
+to place code that drives the application within a package, because a package
+is more easily extended with new code. An application that lives inside a
+package can also be distributed more easily than one which does not live
+within a package.
.. index::
single: creating a project
diff --git a/docs/narr/security.rst b/docs/narr/security.rst
index 63d1cad25..f9fee59dd 100644
--- a/docs/narr/security.rst
+++ b/docs/narr/security.rst
@@ -59,9 +59,6 @@ views are accessible by completely anonymous users. In order to begin
protecting views from execution based on security settings, you need
to enable an authorization policy.
-You can enable an authorization policy imperatively, or declaratively
-via ZCML.
-
Enabling an Authorization Policy Imperatively
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -110,46 +107,8 @@ See also the :mod:`pyramid.authorization` and
:mod:`pyramid.authentication` modules for alternate implementations
of authorization and authentication policies.
-Enabling an Authorization Policy Via ZCML
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you'd rather use :term:`ZCML` to specify an authorization policy
-than imperative configuration, modify the ZCML file loaded by your
-application (usually named ``configure.zcml``) to enable an
-authorization policy.
-
-For example, to enable a policy which compares the value of an "auth
-ticket" cookie passed in the request's environment which contains a
-reference to a single :term:`principal` against the principals present
-in any :term:`ACL` found in model data when attempting to call some
-:term:`view`, modify your ``configure.zcml`` to look something like
-this:
-
-.. code-block:: xml
- :linenos:
-
- <configure xmlns="http://pylonshq.com/pyramid">
-
- <!-- views and other directives before this... -->
-
- <authtktauthenticationpolicy
- secret="iamsosecret"/>
-
- <aclauthorizationpolicy/>
-
- </configure>
-
-"Under the hood", these statements cause an instance of the class
-:class:`pyramid.authentication.AuthTktAuthenticationPolicy` to be
-injected as the :term:`authentication policy` used by this application
-and an instance of the class
-:class:`pyramid.authorization.ACLAuthorizationPolicy` to be
-injected as the :term:`authorization policy` used by this application.
-
-:mod:`pyramid` ships with a number of authorization and
-authentication policy ZCML directives that should prove useful. See
-:ref:`authentication_policies_directives_section` and
-:ref:`authorization_policies_directives_section` for more information.
+You can also enable a security policy declaratively via ZCML. See
+:ref:`zcml_authorization_policy`.
.. index::
single: permissions
@@ -166,19 +125,19 @@ security settings in a :term:`context`, you must pass a
usually just strings, and they have no required composition: you can
name permissions whatever you like.
-For example, the following declaration protects the view named
-``add_entry.html`` when invoked against a ``Blog`` context with the
-``add`` permission:
+For example, the following view declaration protects the view named
+``add_entry.html`` when invoked against a ``Blog`` context with the ``add``
+permission using the :meth:`pyramid.configuration.Configurator.add_view` API:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <view
- context=".models.Blog"
- view=".views.blog_entry_add_view"
- name="add_entry.html"
- permission="add"
- />
+ # config is an instance of pyramid.configuration.Configurator
+
+ config.add_view('mypackage.views.blog_entry_add_view',
+ name='add_entry.html',
+ context='mypackage.models.Blog',
+ permission='add')
The equivalent view registration including the ``add`` permission name
may be performed via the ``@view_config`` decorator:
@@ -195,22 +154,15 @@ may be performed via the ``@view_config`` decorator:
""" Add blog entry code goes here """
pass
-Or the same thing can be done using the
-:meth:`pyramid.configuration.Configurator.add_view` method:
+Or the same thing can be done using the ``permission`` attribute of the ZCML
+:ref:`view_directive` directive.
-.. ignore-next-block
-.. code-block:: python
- :linenos:
-
- config.add_view(blog_entry_add_view,
- context=Blog, name='add_entry.html', permission='add')
-
-As a result of any of these various view configuration statements, if
-an authorization policy is in place when the view callable is found
-during normal application operations, the requesting user will need to
-possess the ``add`` permission against the :term:`context` to be able
-to invoke the ``blog_entry_add_view`` view. If he does not, the
-:term:`Forbidden view` will be invoked.
+As a result of any of these various view configuration statements, if an
+authorization policy is in place when the view callable is found during
+normal application operations, the requesting user will need to possess the
+``add`` permission against the :term:`context` to be able to invoke the
+``blog_entry_add_view`` view. If he does not, the :term:`Forbidden view`
+will be invoked.
.. _setting_a_default_permission:
@@ -348,15 +300,14 @@ The first element of any ACE is either
the ACE matches. The second element is a :term:`principal`. The
third argument is a permission or sequence of permission names.
-A principal is usually a user id, however it also may be a group id if
-your authentication system provides group information and the
-effective :term:`authentication policy` policy is written to respect
-group information. For example, the
-:class:`pyramid.authentication.RepozeWho1AuthenicationPolicy`
-enabled by the ``repozewho1authenticationpolicy`` ZCML directive
-respects group information if you configure it with a ``callback``.
-See :ref:`authentication_policies_directives_section` for more
-information about the ``callback`` attribute.
+A principal is usually a user id, however it also may be a group id if your
+authentication system provides group information and the effective
+:term:`authentication policy` policy is written to respect group information.
+For example, the
+:class:`pyramid.authentication.RepozeWho1AuthenicationPolicy` respects group
+information if you configure it with a ``callback``. See
+:ref:`authentication_policies_directives_section` for more information about
+the ``callback`` attribute.
Each ACE in an ACL is processed by an authorization policy *in the
order dictated by the ACL*. So if you have an ACL like this:
@@ -585,112 +536,6 @@ via print statements when a call to
:func:`pyramid.security.has_permission` fails is often useful.
.. index::
- pair: ZCML directive; authentication policy
-
-.. _authentication_policies_directives_section:
-
-Built-In Authentication Policy ZCML Directives
-----------------------------------------------
-
-Instead of configuring an authentication policy and authorization
-policy imperatively, :mod:`pyramid` ships with a few "pre-chewed"
-authentication policy ZCML directives that you can make use of within
-your application.
-
-``authtktauthenticationpolicy``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When this directive is used, authentication information is obtained
-from an "auth ticket" cookie value, assumed to be set by a custom
-login form.
-
-An example of its usage, with all attributes fully expanded:
-
-.. code-block:: xml
- :linenos:
-
- <authtktauthenticationpolicy
- secret="goshiamsosecret"
- callback=".somemodule.somefunc"
- cookie_name="mycookiename"
- secure="false"
- include_ip="false"
- timeout="86400"
- reissue_time="600"
- max_age="31536000"
- path="/"
- http_only="false"
- />
-
-See :ref:`authtktauthenticationpolicy_directive` for details about
-this directive.
-
-``remoteuserauthenticationpolicy``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When this directive is used, authentication information is obtained
-from a ``REMOTE_USER`` key in the WSGI environment, assumed to
-be set by a WSGI server or an upstream middleware component.
-
-An example of its usage, with all attributes fully expanded:
-
-.. code-block:: xml
- :linenos:
-
- <remoteuserauthenticationpolicy
- environ_key="REMOTE_USER"
- callback=".somemodule.somefunc"
- />
-
-See :ref:`remoteuserauthenticationpolicy_directive` for detailed
-information.
-
-``repozewho1authenticationpolicy``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When this directive is used, authentication information is obtained
-from a ``repoze.who.identity`` key in the WSGI environment, assumed to
-be set by :term:`repoze.who` middleware.
-
-An example of its usage, with all attributes fully expanded:
-
-.. code-block:: xml
- :linenos:
-
- <repozewho1authenticationpolicy
- identifier_name="auth_tkt"
- callback=".somemodule.somefunc"
- />
-
-See :ref:`repozewho1authenticationpolicy_directive` for detailed
-information.
-
-.. index::
- pair: ZCML directive; authorization policy
-
-.. _authorization_policies_directives_section:
-
-Built-In Authorization Policy ZCML Directives
----------------------------------------------
-
-``aclauthorizationpolicy``
-
-When this directive is used, authorization information is obtained
-from :term:`ACL` objects attached to model instances.
-
-An example of its usage, with all attributes fully expanded:
-
-.. code-block:: xml
- :linenos:
-
- <aclauthorizationpolicy/>
-
-In other words, it has no configuration attributes; its existence in a
-``configure.zcml`` file enables it.
-
-See :ref:`aclauthorizationpolicy_directive` for detailed information.
-
-.. index::
single: authentication policy (creating)
.. _creating_an_authentication_policy:
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index ef118d857..c86a279ee 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -102,30 +102,23 @@ press ``return`` after running ``paster serve MyProject.ini``.
request to retrieve the application root. It is not called during
startup, only when a request is handled.
- ``settings`` dictionary contains all the options in the
+ The ``settings`` dictionary contains all the options in the
``[app:main]`` section of our .ini file except the "use" option
(which is internal to paste). In this case, ``**settings`` will be
something like ``{'reload_templates':'true',
'debug_authorization':'false', 'debug_notfound':'false'}``.
-#. The ``app`` function then calls the
- :meth:`pyramid.configuration.Configurator.load_zcml` method,
- passing in a ``zcml_file`` value. ``zcml_file`` is the value of
- the ``configure_zcml`` setting or a default of ``configure.zcml``.
- This filename is relative to the run.py file that the ``app``
- function lives in. The ``load_zcml`` function processes each
- :term:`ZCML declaration` in the ZCML file implied by the
- ``zcml_file`` argument. If ``load_zcml`` fails to parse the ZCML
- file (or any file which is included by the ZCML file), a
- ``XMLConfigurationError`` is raised and processing ends. If it
- succeeds, an :term:`application registry` is populated using all
- the :term:`ZCML declaration` statements present in the file.
-
-#. The :meth:`pyramid.configuration.Configurator.make_wsgi_app`
- method is called. The result is a :term:`router` instance. The
- router is associated with the :term:`application registry` implied
- by the configurator previously populated by ZCML. The router is a
- WSGI application.
+#. The ``app`` function then calls various methods on the an instance of the
+ class :class:`pyramid.configuration.Configurator` method. The intent of
+ calling these methods is to populate an :term:`application registry`,
+ which represents the :mod:`pyramid` configuration related to the
+ application.
+
+#. The :meth:`pyramid.configuration.Configurator.make_wsgi_app` method is
+ called. The result is a :term:`router` instance. The router is
+ associated with the :term:`application registry` implied by the
+ configurator previously populated by other methods run against the
+ Configurator. The router is a WSGI application.
#. A :class:`pyramid.interfaces.IApplicationCreated` event is
emitted (see :ref:`events_chapter` for more information about
diff --git a/docs/narr/static.rst b/docs/narr/static.rst
index 02ee68eb6..a60b84445 100644
--- a/docs/narr/static.rst
+++ b/docs/narr/static.rst
@@ -6,88 +6,65 @@ resources from a directory on a filesystem. This chapter describes
how to configure :mod:`pyramid` to do so.
.. index::
- triple: view; zcml; static resource
single: add_static_view
.. _static_resources_section:
-Serving Static Resources Using a ZCML Directive
------------------------------------------------
-
-Use of the ``static`` ZCML directive or the
-:meth:`pyramid.configuration.configurator.add_static_view` method
-is the preferred way to instruct :mod:`pyramid` to serve static
-resources such as JavaScript and CSS files. This mechanism makes
-static files available at a name relative to the application root URL,
-e.g. ``/static``.
-
-Note that the ``path`` provided to ``static`` may be a fully qualified
-:term:`resource specification`, a package-relative path, or an
-*absolute path*. The ``path`` with the value ``a/b/c/static`` of a
-``static`` directive in a ZCML file that resides in the "mypackage"
-package will resolve to a package-qualified resource such as
-``some_package:a/b/c/static``.
-
-Here's an example of a ``static`` ZCML directive that will serve files
-up under the ``/static`` URL from the ``/var/www/static`` directory of
-the computer which runs the :mod:`pyramid` application using an
-absolute path.
-
-.. code-block:: xml
- :linenos:
+Serving Static Resources
+------------------------
+
+Use the :meth:`pyramid.configuration.Configurator.add_static_view` to
+instruct :mod:`pyramid` to serve static resources such as JavaScript and CSS
+files. This mechanism makes static files available at a name relative to the
+application root URL, e.g. ``/static``.
- <static
- name="static"
- path="/var/www/static"
- />
+Note that the ``path`` provided to
+:meth:`pyramid.configuration.Configurator.add_static_view` may be a fully
+qualified :term:`resource specification` or an *absolute path*.
-Here's an example of a ``static`` directive that will serve files up
-under the ``/static`` URL from the ``a/b/c/static`` directory of the
-Python package named ``some_package`` using a fully qualified
-:term:`resource specification`.
+Here's an example of a use of
+:meth:`pyramid.configuration.Configurator.add_static_view` that will serve
+files up under the ``/static`` URL from the ``/var/www/static`` directory of
+the computer which runs the :mod:`pyramid` application using an absolute
+path.
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <static
- name="static"
- path="some_package:a/b/c/static"
- />
+ # config is an instance of pyramid.configuration.Configurator
+ config.add_static_view(name='static', path='/var/www/static')
-Here's an example of a ``static`` directive that will serve files up
-under the ``/static`` URL from the ``static`` directory of the Python
-package in which the ``configure.zcml`` file lives using a
-package-relative path.
+Here's an example of
+:meth:`pyramid.configuration.Configurator.add_static_view` that will serve
+files up under the ``/static`` URL from the ``a/b/c/static`` directory of the
+Python package named ``some_package`` using a fully qualified :term:`resource
+specification`.
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <static
- name="static"
- path="static"
- />
-
-Whether you use for ``path`` a fully qualified resource specification,
-an absolute path, or a package-relative path, When you place your
-static files on the filesystem in the directory represented as the
-``path`` of the directive, you will then be able to view the static
-files in this directory via a browser at URLs prefixed with the
-directive's ``name``. For instance if the ``static`` directive's
+ # config is an instance of pyramid.configuration.Configurator
+ config.add_static_view(name='static', path='some_package:a/b/c/static')
+
+Whether you use for ``path`` a fully qualified resource specification, or an
+absolute path, when you place your static files on the filesystem in the
+directory represented as the ``path`` of the directive, you will then be able
+to view the static files in this directory via a browser at URLs prefixed
+with the directive's ``name``. For instance if the ``static`` directive's
``name`` is ``static`` and the static directive's ``path`` is
-``/path/to/static``, ``http://localhost:6543/static/foo.js`` will
-return the file ``/path/to/static/dir/foo.js``. The static directory
-may contain subdirectories recursively, and any subdirectories may
-hold files; these will be resolved by the static view as you would
-expect.
-
-While the ``path`` argument can be a number of different things, the
-``name`` argument of the ``static`` ZCML directive can also be one of
-a number of things: a *view name* or a *URL*. The above examples have
-shown usage of the ``name`` argument as a view name. When ``name`` is
-a *URL* (or any string with a slash (``/``) in it), static resources
-can be served from an external webserver. In this mode, the ``name``
-is used as the URL prefix when generating a URL using
-:func:`pyramid.url.static_url`.
+``/path/to/static``, ``http://localhost:6543/static/foo.js`` will return the
+file ``/path/to/static/dir/foo.js``. The static directory may contain
+subdirectories recursively, and any subdirectories may hold files; these will
+be resolved by the static view as you would expect.
+
+While the ``path`` argument can be a number of different things, the ``name``
+argument of the call to
+:meth:`pyramid.configuration.Configurator.add_static_view` can also be one of
+a number of things: a *view name* or a *URL*. The above examples have shown
+usage of the ``name`` argument as a view name. When ``name`` is a *URL* (or
+any string with a slash (``/``) in it), static resources can be served from
+an external webserver. In this mode, the ``name`` is used as the URL prefix
+when generating a URL using :func:`pyramid.url.static_url`.
.. note::
@@ -109,32 +86,30 @@ is used as the URL prefix when generating a URL using
for a pattern; any setting name other than ``media_location`` could
be used.
-For example, the ``static`` ZCML directive may be fed a ``name``
-argument which is ``http://example.com/images``:
+For example, :meth:`pyramid.configuration.Configurator.add_static_view` may
+be fed a ``name`` argument which is ``http://example.com/images``:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <static
- name="http://example.com/images"
- path="mypackage:images"
- />
-
-Because the ``static`` ZCML directive is 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.configuration.Configurator.add_static_view` will
-generate a URL something like ``http://example.com/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.
-
-The :meth:`pyramid.configuration.Configurator.add_static_view`
-method offers an imperative equivalent to the ``static`` ZCML
-directive. Use of the ``add_static_view`` imperative configuration
-method is completely equivalent to using ZCML for the same purpose.
+ # config is an instance of pyramid.configuration.Configurator
+ config.add_static_view(name='http://example.com/images',
+ path='mypackage:images')
+
+Because :meth:`pyramid.configuration.Configurator.add_static_view` is
+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.configuration.Configurator.add_static_view`
+will generate a URL something like ``http://example.com/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.
+
+The :ref:`static_directive` ZCML directive offers an declarative equivalent
+to :meth:`pyramid.configuration.Configurator.add_static_view`. Use of the
+:ref:`static_directive` ZCML directive is completely equivalent to using
+imperative configuration for the same purpose.
.. index::
single: generating static resource urls
@@ -145,42 +120,30 @@ method is completely equivalent to using ZCML for the same purpose.
Generating Static Resource URLs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When a :ref:`static_directive` ZCML directive or a call to the
-``add_static_view`` method of a
-:class:`pyramid.configuration.Configurator` is used to register a
-static resource directory, a special helper API named
-:func:`pyramid.static_url` can be used to generate the appropriate
-URL for a package resource that lives in one of the directories named
-by the static registration ``path`` attribute.
+When a :meth:`pyramid.configuration.Configurator.add_static_view`` method is
+used to register a static resource directory, a special helper API named
+:func:`pyramid.static_url` can be used to generate the appropriate URL for a
+package resource that lives in one of the directories named by the static
+registration ``path`` attribute.
-For example, let's assume you create a set of ``static`` declarations
-in ZCML like so:
+For example, let's assume you create a set of static declarations like so:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <static
- name="static1"
- path="resources/1"
- />
-
- <static
- name="static2"
- path="resources/2"
- />
+ 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 the ``resources/1`` directory are consulted when a user
-visits a URL which begins with ``/static1``, and the resources in the
-``resources/2`` directory are consulted when a user visits a URL which
-begins with ``/static2``.
+These declarations create URL-accessible directories which have URLs which
+begin, respectively, with ``/static1`` and ``/static2``. 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
+user visits a URL which begins with ``/static2``.
You needn't generate the URLs to static resources "by hand" in such a
configuration. Instead, use the :func:`pyramid.url.static_url` API
-to generate them for you. For example, let's imagine that the
-following code lives in a module that shares the same directory as the
-above ZCML file:
+to generate them for you. For example:
.. code-block:: python
:linenos:
@@ -189,8 +152,8 @@ above ZCML file:
from pyramid.chameleon_zpt import render_template_to_response
def my_view(request):
- css_url = static_url('resources/1/foo.css', request)
- js_url = static_url('resources/2/foo.js', request)
+ css_url = static_url('mypackage:resources/1/foo.css', request)
+ js_url = static_url('mypackage:resources/2/foo.js', request)
return render_template_to_response('templates/my_template.pt',
css_url = css_url,
js_url = js_url)
@@ -200,29 +163,23 @@ If the request "application URL" of the running system is
``http://example.com/static1/foo.css``. The ``js_url`` generated
above would be ``http://example.com/static2/foo.js``.
-One benefit of using the :func:`pyramid.url.static_url` function
-rather than constructing static URLs "by hand" is that if you need to
-change the ``name`` of a static URL declaration in ZCML, the generated
-URLs will continue to resolve properly after the rename.
-
-URLs may also be generated by :func:`pyramid.url.static_url` to
-static resources that live *outside* the :mod:`pyramid`
-application. This will happen when the ``name`` argument provided to
-the ``static`` ZCML directive or the
-:meth:`pyramid.configuration.Configurator.add_static_view` API
-associated with the path fed to :func:`pyramid.url.static_url` is a
-*URL* instead of a view name. For example, the ``name`` argument
-given to either the ZCML directive or the configurator API may be
+One benefit of using the :func:`pyramid.url.static_url` function rather than
+constructing static URLs "by hand" is that if you need to change the ``name``
+of a static URL declaration, the generated URLs will continue to resolve
+properly after the rename.
+
+URLs may also be generated by :func:`pyramid.url.static_url` to static
+resources that live *outside* the :mod:`pyramid` application. This will
+happen when the :meth:`pyramid.configuration.Configurator.add_static_view`
+API associated with the path fed to :func:`pyramid.url.static_url` is a *URL*
+instead of a view name. For example, the ``name`` argument may be
``http://example.com`` while the the ``path`` given may be
``mypackage:images``:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <static
- name="static1"
- path="mypackage:images"
- />
+ config.add_static_view(name='static1', path='mypackage:images')
Under such a configuration, the URL generated by ``static_url`` for
resources which begin with ``mypackage:images`` will be prefixed with
@@ -270,34 +227,27 @@ your application root as below.
"here-relative", it is relative to the package of the module in
which the static view is defined.
-Subsequently, you may wire this view up to be accessible as
-``/static`` using either the
-:mod:`pyramid.configuration.Configurator.add_view` method or the
-``<view>`` ZCML directive in your application's ``configure.zcml``
-against either the class or interface that represents your root
-object. For example (ZCML):
-
-.. code-block:: xml
+Subsequently, you may wire this view up to be accessible as ``/static`` using
+the :mod:`pyramid.configuration.Configurator.add_view` method in your
+application's startup code against either the class or interface that
+represents your root object.
+
+.. code-block:: python
:linenos:
- <view
- context=".models.Root"
- view=".static.static_view"
- name="static"
- />
+ config.add_view('mypackage.static.static_view', name='static',
+ context='mypackage.models.Root')
-In this case, ``.models.Root`` refers to the class of which your
+In this case, ``mypackage.models.Root`` refers to the class of which your
:mod:`pyramid` application's root object is an instance.
-You can also provide a ``context`` of ``*`` 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.
+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.
-Note that you cannot use the :func:`pyramid.static_url` API to
-generate URLs against resources made accessible by registering a
-custom static view.
+Note that you cannot use the :func:`pyramid.static_url` API to generate URLs
+against resources made accessible by registering a custom static view.
.. warning::
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index f5fa87fce..2ad086ac7 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -35,11 +35,15 @@ hierarchy, URL dispatch is easier to use than traversal, and is often
a more natural fit for creating an application that manipulates "flat"
data.
-The presence of :ref:`route_directive` statements in a :term:`ZCML`
-file used by your application or the presence of calls to the
-:meth:`pyramid.configuration.Configurator.add_route` method in
-imperative configuration within your application is a sign that you're
-using :term:`URL dispatch`.
+The presence of calls to the
+:meth:`pyramid.configuration.Configurator.add_route` method in imperative
+configuration within your application is a sign that you're using :term:`URL
+dispatch`.
+
+..note::
+
+ Route configuration may also be added to the system via term:`ZCML` (see
+ :ref:`zcml_route_configuration`).
High-Level Operational Overview
-------------------------------
@@ -72,14 +76,11 @@ application to uniquely identify a particular route when generating a
URL. It also optionally has a ``factory``, a set of :term:`route
predicate` parameters, and a set of :term:`view` parameters.
-A route configuration may be added to the system via :term:`imperative
-configuration` or via :term:`ZCML`. Both are completely equivalent.
-
.. index::
single: add_route
-Configuring a Route Imperatively via The ``add_route`` Configurator Method
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Configuring a Route via The ``add_route`` Configurator Method
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The :meth:`pyramid.configuration.Configurator.add_route` method
adds a single :term:`route configuration` to the :term:`application
@@ -95,42 +96,7 @@ registry`. Here's an example:
config.add_route('myroute', '/prefix/:one/:two', view=myview)
.. index::
- single: ZCML directive; route
-
-Configuring a Route via ZCML
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Instead of using the imperative
-:meth:`pyramid.configuration.Configurator.add_route` method to add
-a new route, you can alternately use :term:`ZCML`. For example, the
-following :term:`ZCML declaration` causes a route to be added to the
-application.
-
-.. code-block:: xml
- :linenos:
-
- <route
- name="myroute"
- pattern="/prefix/:one/:two"
- view=".views.myview"
- />
-
-.. note::
-
- Values prefixed with a period (``.``) within the values of ZCML
- attributes such as the ``view`` attribute of a ``route`` mean
- "relative to the Python package directory in which this
- :term:`ZCML` file is stored". So if the above ``route``
- declaration was made inside a ``configure.zcml`` file that lived in
- the ``hello`` package, you could replace the relative
- ``.views.myview`` with the absolute ``hello.views.myview`` 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.
-
-
-See :ref:`route_directive` for full ``route`` ZCML directive
-documentation.
+ single: route configuration; view callable
Route Configuration That Names a View Callable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -144,14 +110,26 @@ information about how to create view callables, see
Here's an example route configuration that references a view callable:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- name="myroute"
- pattern="/prefix/:one/:two"
- view="mypackage.views.myview"
- />
+ # "config" below is presumed to be an instance of the
+ # pyramid.configuration.Configurator class; "myview" is assumed
+ # to be a "view callable" function
+ from myproject.views import myview
+ config.add_route('myroute', '/prefix/:one/:two', view=myview)
+
+You can also pass a :term:`dotted Python name` as the ``view`` argument
+rather than an actual callable:
+
+.. code-block:: python
+ :linenos:
+
+ # "config" below is presumed to be an instance of the
+ # pyramid.configuration.Configurator class; "myview" is assumed
+ # to be a "view callable" function
+ from myproject.views import myview
+ config.add_route('myroute', '/prefix/:one/:two', 'myproject.views.myview')
When a route configuration names a ``view`` attribute, the :term:`view
callable` named as that ``view`` attribute will always be found and
@@ -365,15 +343,12 @@ they are added to the application at startup time. This is unlike
:term:`traversal`, which depends on emergent behavior which happens as
a result of traversing a graph.
-The order that routes are evaluated when they are defined via
-:term:`ZCML` is the order in which they appear in the ZCML relative to
-each other. For routes added via the
-:mod:`pyramid.configuration.Configurator.add_route` method, the
-order that routes are evaluated is the order in which they are added
-to the configuration imperatively.
+For routes added via the :mod:`pyramid.configuration.Configurator.add_route`
+method, the order that routes are evaluated is the order in which they are
+added to the configuration imperatively.
-For example, route configuration statements with the following
-patterns might be added in the following order:
+For example, route configuration statements with the following patterns might
+be added in the following order:
.. code-block:: text
@@ -401,14 +376,14 @@ the route is used to generate a :term:`root` object. This object will
usually be used as the :term:`context` of the view callable ultimately
found via :term:`view lookup`.
-.. code-block:: xml
+.. code-block:: python
+ :linenos:
+
+ config.add_route('abc', '/abc', 'myproject.views.theview',
+ factory='myproject.models.root_factory')
- <route
- pattern="/abc"
- name="abc"
- view=".views.theview"
- factory=".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.
In this way, each route can use a different factory, making it
possible to supply a different :term:`context` object to the view
@@ -425,7 +400,7 @@ within :ref:`hybrid_chapter`.
Route Configuration Arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Route configuration statements may specify a large number of
+Route configuration ``add_route`` statements may specify a large number of
arguments.
Many of these arguments are :term:`route predicate` arguments. A
@@ -647,11 +622,10 @@ represent neither predicates nor view configuration information.
Custom Route Predicates
~~~~~~~~~~~~~~~~~~~~~~~
-Each of the predicate callables fed to the ``custom_predicates``
-argument of :meth:`pyramid.configuration.Configurator.add_route` or
-the ``custom_predicates`` ZCML attribute must be a callable accepting
-two arguments. The first argument passed to a custom predicate is a
-dictionary conventionally named ``info``. The second argument is the
+Each of the predicate callables fed to the ``custom_predicates`` argument of
+:meth:`pyramid.configuration.Configurator.add_route` must be a callable
+accepting two arguments. The first argument passed to a custom predicate is
+a dictionary conventionally named ``info``. The second argument is the
current :term:`request` object.
The ``info`` dictionary has a number of contained values: ``match`` is
@@ -825,10 +799,7 @@ Routing Examples
Let's check out some examples of how route configuration statements
might be commonly declared, and what will happen if they are matched
-by the information present in a request. The examples that follow
-assume that :term:`ZCML` will be used to perform route configuration,
-although you can use :term:`imperative configuration` equivalently if
-you like.
+by the information present in a request.
.. _urldispatch_example1:
@@ -838,14 +809,10 @@ Example 1
The simplest route declaration which configures a route match to
*directly* result in a particular view callable being invoked:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- name="idea"
- pattern="site/:id"
- view="mypackage.views.site_view"
- />
+ config.add_route('idea', 'site/:id', view='mypackage.views.site_view')
When a route configuration with a ``view`` attribute is added to the
system, and an incoming request matches the *pattern* of the route
@@ -888,26 +855,12 @@ Example 2
Below is an example of a more complicated set of route statements you
might add to your application:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- name="idea"
- pattern="ideas/:idea"
- view="mypackage.views.idea_view"
- />
-
- <route
- name="user"
- pattern="users/:user"
- view="mypackage.views.user_view"
- />
-
- <route
- name="tag"
- pattern="tags/:tag"
- view="mypackage.views.tag_view"
- />
+ config.add_route('idea', 'ideas/:idea', view='mypackage.views.idea_view')
+ config.add_route('user', 'users/:user', view='mypackage.views.user_view')
+ config.add_route('tag', 'tags/:tags', view='mypackage.views.tag_view')
The above configuration will allow :mod:`pyramid` to service URLs
in these forms:
@@ -944,28 +897,24 @@ URL by the process will be passed to the view callable.
Example 3
~~~~~~~~~
-The context object passed in to a view found as the result of URL
-dispatch will, by default, be an instance of the object returned by
-the :term:`root factory` configured at startup time (the
-``root_factory`` argument to the :term:`Configurator` used to
-configure the application).
+The context object passed in to a view found as the result of URL dispatch
+will, by default, be an instance of the object returned by the :term:`root
+factory` configured at startup time (the ``root_factory`` argument to the
+:term:`Configurator` used to configure the application).
-You can override this behavior by passing in a ``factory`` argument to
-the ZCML directive for a particular route. The ``factory`` should be
-a callable that accepts a :term:`request` and returns an instance of a
-class that will be the context used by the view.
+You can override this behavior by passing in a ``factory`` argument to the
+:meth:`pyramid.configuration.Configurator.add_route` method for a particular
+route. The ``factory`` should be a callable that accepts a :term:`request`
+and returns an instance of a class that will be the context used by the view.
An example of using a route with a factory:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- name="idea"
- pattern="ideas/:idea"
- view=".views.idea_view"
- factory=".models.Idea"
- />
+ config.add_route('idea', 'ideas/:idea',
+ view='myproject.views.idea_view',
+ factory='myproject.models.Idea')
The above route will manufacture an ``Idea`` model as a
:term:`context`, assuming that ``mypackage.models.Idea`` resolves to a
@@ -988,31 +937,20 @@ It is possible to create a route declaration without a ``view``
attribute, but associate the route with a :term:`view callable` using
a ``view`` declaration.
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- name="idea"
- pattern="site/:id"
- />
-
- <view
- view="mypackage.views.site_view"
- route_name="idea"
- />
+ config.add_route('idea', 'site/:id')
+ config.add_view(route_name='idea', view='mypackage.views.site_view')
This set of configuration parameters creates a configuration
completely equivalent to this example provided in
:ref:`urldispatch_example1`:
-.. code-block:: xml
+.. code-block:: python
:linenos:
- <route
- name="idea"
- pattern="site/:id"
- view="mypackage.views.site_view"
- />
+ config.add_route('idea', 'site/:id', view='mypackage.views.site_view')
In fact, the spelling which names a ``view`` attribute is just
syntactic sugar for the more verbose spelling which contains separate
@@ -1028,29 +966,21 @@ in :ref:`hybrid_chapter`.
Matching the Root URL
---------------------
-It's not entirely obvious how to use a route pattern to match the root
-URL ("/"). To do so, give the empty string as a pattern in a ZCML
-``route`` declaration:
+It's not entirely obvious how to use a route pattern to match the root URL
+("/"). To do so, give the empty string as a pattern in a call to
+:meth:`pyramid.configuration.Configurator.add_route`:
.. code-block:: xml
:linenos:
- <route
- pattern=""
- name="root"
- view=".views.root_view"
- />
+ config.add_route('root', '', 'mypackage.views.root_view')
Or provide the literal string ``/`` as the pattern:
.. code-block:: xml
:linenos:
- <route
- pattern="/"
- name="root"
- view=".views.root_view"
- />
+ config.add_route('root', '/', 'mypackage.views.root_view')
.. index::
single: generating route URLs
@@ -1059,10 +989,9 @@ Or provide the literal string ``/`` as the pattern:
Generating Route URLs
---------------------
-Use the :func:`pyramid.url.route_url` function to generate URLs
-based on route patterns. For example, if you've configured a route in
-ZCML with the ``name`` "foo" and the ``pattern`` ":a/:b/:c", you might
-do this.
+Use the :func:`pyramid.url.route_url` function to generate URLs based on
+route patterns. For example, if you've configured a route with the ``name``
+"foo" and the ``pattern`` ":a/:b/:c", you might do this.
.. ignore-next-block
.. code-block:: python
@@ -1101,15 +1030,8 @@ your route configuration looks like so:
.. code-block:: xml
:linenos:
- <route
- view=".views.no_slash"
- pattern="no_slash"
- />
-
- <route
- view=".views.has_slash"
- pattern="has_slash/"
- />
+ config.add_route('noslash', 'no_slash', 'myproject.views.no_slash')
+ config.add_route('hasslash', 'has_slash/', 'myproject.views.has_slash')
If a request enters the application with the ``PATH_INFO`` value of
``/no_slash``, the first route will match. If a request enters the
@@ -1126,27 +1048,14 @@ redirect to ``/has_slash/`` will be returned to the user's browser.
Note that this will *lose* ``POST`` data information (turning it into
a GET), so you shouldn't rely on this to redirect POST requests.
-To configure the slash-appending not found view in your application,
-change the application's ``configure.zcml``, adding the following
-stanza:
+To configure the slash-appending not found view in your application, change
+the application's startup configuration, adding the following stanza:
.. code-block:: xml
:linenos:
- <view
- context="pyramid.exceptions.NotFound"
- view="pyramid.view.append_slash_notfound_view"
- />
-
-Or use the :meth:`pyramid.configuration.Configurator.add_view`
-method if you don't use ZCML:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.exceptions import NotFound
- from pyramid.view import append_slash_notfound_view
- config.add_view(append_slash_notfound_view, context=NotFound)
+ config.add_view(context='pyramid.exceptions.NotFound',
+ view='pyramid.view.append_slash_notfound_view')
See :ref:`view_module` and :ref:`changing_the_notfound_view` for more
information about the slash-appending not found view and for a more
@@ -1227,44 +1136,17 @@ following in the ``mypackage.run`` module:
environ = event.request.environ
environ['mypackage.sqlcleaner'] = Cleanup(DBSession.remove)
-Then in the ``configure.zcml`` of your package, inject the following:
-
-.. code-block:: xml
-
- <subscriber for="pyramid.interfaces.INewRequest"
- handler="mypackage.run.handle_teardown"/>
-
-Or, if you don't use ZCML, but you do use a :term:`scan` add a
-subscriber decorator:
+Then add an event subscriber in your startup configuration:
.. code-block:: python
+ :linenos:
- from pyramid.events import subscriber
- from pyramid.interfaces import INewRequest
-
- @subscriber(INewRequest)
- def handle_teardown(event):
- environ = event.request.environ
- environ['mypackage.sqlcleaner'] = Cleanup(DBSession.remove)
-
-Or finally, it can be done imperatively via the ``add_subscriber``
-method of a :term:`Configurator`.
-
-.. code-block:: python
-
- from pyramid.interfaces import INewRequest
- from pyramid.configuration imoport Configurator
-
- def handle_teardown(event):
- environ = event.request.environ
- environ['mypackage.sqlcleaner'] = Cleanup(DBSession.remove)
-
- config = Configurator()
- config.add_subscriber(handle_teardown, INewRequest)
+ config.add_subscriber('mypackage.run.handle_teardown',
+ 'pyramid.events.NewRequest')
-Any of the above three ways to register a handle_teardown subscriber
-will cause the DBSession to be removed whenever the WSGI environment
-is destroyed (usually at the end of every request).
+Registering a handle_teardown subscriber will cause the DBSession to be
+removed whenever the WSGI environment is destroyed (usually at the end of
+every request).
.. note:: This is only an example. In particular, it is not necessary
to cause ``DBSession.remove`` to be called as the result of an