Skip to content
This repository
branch: requestresponse
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 207 lines (162 sloc) 9.763 kb

Basic Layout

The starter files generated by the pyramid_zodb scaffold are basic, but they provide a good orientation for the high-level patterns common to most :term:`traversal` -based :app:`Pyramid` (and :term:`ZODB` based) projects.

System Message: ERROR/3 (<string>, line 5); backlink

Unknown interpreted text role "term".

System Message: ERROR/3 (<string>, line 5); backlink

Unknown interpreted text role "app".

System Message: ERROR/3 (<string>, line 5); backlink

Unknown interpreted text role "term".

The source code for this tutorial stage can be browsed via http://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki/src/basiclayout/.

App Startup with __init__.py

A directory on disk can be turned into a Python :term:`package` by containing an __init__.py file. Even if empty, this marks a directory as a Python package. Our application uses __init__.py as both a package marker, as well as to contain application configuration code.

System Message: ERROR/3 (<string>, line 16); backlink

Unknown interpreted text role "term".

When you run the application using the paster command using the development.ini generated config file, the application configuration points at a Setuptools entry point described as egg:tutorial. In our application, because the application's setup.py file says so, this entry point happens to be the main function within the file named __init__.py:

System Message: ERROR/3 (<string>, line 28)

Unknown directive type "literalinclude".

.. literalinclude:: src/basiclayout/tutorial/__init__.py
   :linenos:
   :language: py

  1. Lines 1-3. Perform some dependency imports.

  2. Line 8. Get the ZODB configuration from the development.ini file's [app:main] section represented by the settings dictionary passed to our app function. This will be a URI (something like file:///path/to/Data.fs).

  3. Line 12. We create a "finder" object using the PersistentApplicationFinder helper class, passing it the ZODB URI and the "appmaker" we've imported from models.py.

  4. Lines 13 - 14. We create a :term:`root factory` which uses the finder to return a ZODB root object.

    System Message: ERROR/3 (<string>, line 43); backlink

    Unknown interpreted text role "term".

  5. Line 15. We construct a :term:`Configurator` with a :term:`root factory` and the settings keywords parsed by PasteDeploy. The root factory is named get_root.

    System Message: ERROR/3 (<string>, line 46); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 46); backlink

    Unknown interpreted text role "term".

  6. Line 16. Register a 'static view' which answers requests which start with with URL path /static using the :meth:`pyramid.config.Configurator.add_static_view method`. This statement registers a view that will serve up static assets, such as CSS and image files, for us, in this case, at http://localhost:6543/static/ and below. The first argument is the "name" static, which indicates that the URL path prefix of the view will be /static. the The second argument of this tag is the "path", which is an :term:`asset specification`, so it finds the resources it should serve within the static directory inside the tutorial package.

    System Message: ERROR/3 (<string>, line 50); backlink

    Unknown interpreted text role "meth".

    System Message: ERROR/3 (<string>, line 50); backlink

    Unknown interpreted text role "term".

  7. Line 17. Perform a :term:`scan`. A scan will find :term:`configuration decoration`, such as view configuration decorators (e.g. @view_config) in the source code of the tutorial package and will take actions based on these decorators. The argument to :meth:`~pyramid.config.Configurator.scan` is the package name to scan, which is tutorial.

    System Message: ERROR/3 (<string>, line 62); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 62); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 62); backlink

    Unknown interpreted text role "meth".

  8. Line 18. Use the :meth:`pyramid.config.Configurator.make_wsgi_app` method to return a :term:`WSGI` application.

    System Message: ERROR/3 (<string>, line 69); backlink

    Unknown interpreted text role "meth".

    System Message: ERROR/3 (<string>, line 69); backlink

    Unknown interpreted text role "term".

Resources and Models with models.py

:app:`Pyramid` uses the word :term:`resource` to describe objects arranged hierarchically in a :term:`resource tree`. This tree is consulted by :term:`traversal` to map URLs to code. In this application, the resource tree represents the site structure, but it also represents the :term:`domain model` of the application, because each resource is a node stored persistently in a :term:`ZODB` database. The models.py file is where the pyramid_zodb scaffold put the classes that implement our resource objects, each of which happens also to be a domain model object.

System Message: ERROR/3 (<string>, line 76); backlink

Unknown interpreted text role "app".

System Message: ERROR/3 (<string>, line 76); backlink

Unknown interpreted text role "term".

System Message: ERROR/3 (<string>, line 76); backlink

Unknown interpreted text role "term".

System Message: ERROR/3 (<string>, line 76); backlink

Unknown interpreted text role "term".

System Message: ERROR/3 (<string>, line 76); backlink

Unknown interpreted text role "term".

System Message: ERROR/3 (<string>, line 76); backlink

Unknown interpreted text role "term".

Here is the source for models.py:

System Message: ERROR/3 (<string>, line 87)

Unknown directive type "literalinclude".

.. literalinclude:: src/basiclayout/tutorial/models.py
   :linenos:
   :language: py

  1. Lines 3-4. The MyModel :term:`resource` class is implemented here. Instances of this class will be capable of being persisted in :term:`ZODB` because the class inherits from the :class:`persistent.mapping.PersistentMapping` class. The __parent__ and __name__ are important parts of the :term:`traversal` protocol. By default, have these as None indicating that this is the :term:`root` object.

    System Message: ERROR/3 (<string>, line 91); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 91); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 91); backlink

    Unknown interpreted text role "class".

    System Message: ERROR/3 (<string>, line 91); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 91); backlink

    Unknown interpreted text role "term".

  2. Lines 6-12. appmaker is used to return the application root object. It is called on every request to the :app:`Pyramid` application. It also performs bootstrapping by creating an application root (inside the ZODB root object) if one does not already exist.

    System Message: ERROR/3 (<string>, line 99); backlink

    Unknown interpreted text role "app".

    We do so by first seeing if the database has the persistent application root. If not, we make an instance, store it, and commit the transaction. We then return the application root object.

Views With views.py

Our scaffold generated a default views.py on our behalf. It contains a single view, which is used to render the page shown when you visit the URL http://localhost:6543/.

Here is the source for views.py:

System Message: ERROR/3 (<string>, line 119)

Unknown directive type "literalinclude".

.. literalinclude:: src/basiclayout/tutorial/views.py
   :linenos:
   :language: py

Let's try to understand the components in this module:

  1. Lines 1-2. Perform some dependency imports.

  2. Line 4. Use the :func:`pyramid.view.view_config` :term:`configuration decoration` to perform a :term:`view configuration` registration. This view configuration registration will be activated when the application is started. It will be activated by virtue of it being found as the result of a :term:`scan` (when Line 17 of __init__.py is run).

    System Message: ERROR/3 (<string>, line 127); backlink

    Unknown interpreted text role "func".

    System Message: ERROR/3 (<string>, line 127); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 127); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 127); backlink

    Unknown interpreted text role "term".

    The @view_config decorator accepts a number of keyword arguments. We use two keyword arguments here: context and renderer.

    The context argument signifies that the decorated view callable should only be run when :term:`traversal` finds the tutorial.models.MyModel :term:`resource` to be the :term:`context` of a request. In English, this means that when the URL / is visited, because MyModel is the root model, this view callable will be invoked.

    System Message: ERROR/3 (<string>, line 136); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 136); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 136); backlink

    Unknown interpreted text role "term".

    The renderer argument names an :term:`asset specification` of tutorial:templates/mytemplate.pt. This asset specification points at a :term:`Chameleon` template which lives in the mytemplate.pt file within the templates directory of the tutorial package. And indeed if you look in the templates directory of this package, you'll see a mytemplate.pt template file, which renders the default home page of the generated project.

    System Message: ERROR/3 (<string>, line 142); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 142); backlink

    Unknown interpreted text role "term".

    Since this call to @view_config doesn't pass a name argument, the my_view function which it decorates represents the "default" view callable used when the context is of the type MyModel.

  3. Lines 5-6. We define a :term:`view callable` named my_view, which we decorated in the step above. This view callable is a function we write generated by the pyramid_zodb scaffold that is given a request and which returns a dictionary. The mytemplate.pt :term:`renderer` named by the asset specification in the step above will convert this dictionary to a :term:`response` on our behalf.

    System Message: ERROR/3 (<string>, line 154); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 154); backlink

    Unknown interpreted text role "term".

    System Message: ERROR/3 (<string>, line 154); backlink

    Unknown interpreted text role "term".

    The function returns the dictionary {'project':'tutorial'}. This dictionary is used by the template named by the mytemplate.pt asset specification to fill in certain values on the page.

The WSGI Pipeline in development.ini

The development.ini (in the tutorial :term:`project` directory, as opposed to the tutorial :term:`package` directory) looks like this:

System Message: ERROR/3 (<string>, line 168); backlink

Unknown interpreted text role "term".

System Message: ERROR/3 (<string>, line 168); backlink

Unknown interpreted text role "term".

System Message: ERROR/3 (<string>, line 171)

Unknown directive type "literalinclude".

.. literalinclude:: src/views/development.ini
   :language: ini


Note the existence of a [pipeline:main] section which specifies our WSGI pipeline. This "pipeline" will be served up as our WSGI application. As far as the WSGI server is concerned the pipeline is our application. Simpler configurations don't use a pipeline: instead they expose a single WSGI application as "main". Our setup is more complicated, so we use a pipeline composed of :term:`middleware`.

System Message: ERROR/3 (<string>, line 175); backlink

Unknown interpreted text role "term".

The egg:WebError#evalerror middleware is at the "top" of the pipeline. This is middleware which displays debuggable errors in the browser while you're developing (not recommended for a production system).

The egg:repoze.zodbconn#closer middleware is in the middle of the pipeline. This is a piece of middleware which closes the ZODB connection opened by the PersistentApplicationFinder at the end of the request.

The egg:repoze.retry#retry middleware catches ConflictError exceptions from ZODB and retries the request up to three times (ZODB is an optimistic concurrency database that relies on application-level transaction retries when a conflict occurs).

The tm middleware is the last piece of middleware in the pipeline. This commits a transaction near the end of the request unless there's an exception raised or the HTTP response code is an error code. The tm refers to the [filter:tm] section beneath the pipeline declaration, which configures the transaction manager.

The final line in the [pipeline:main] section is tutorial, which refers to the [app:tutorial] section above it. The [app:tutorial] section is the section which actually defines our application settings. The values within this section are passed as **settings to the main function we defined in __init__.py when the server is started via paster serve.

Something went wrong with that request. Please try again.