Basic Layout

The starter files generated by the pyramid_routesalchemy template are basic, but they provide a good orientation for the high-level patterns common to most url dispatch -based Pyramid projects.

The source code for this tutorial stage can be browsed at http://github.com/Pylons/pyramid/tree/1.0-branch/docs/tutorials/wiki2/src/basiclayout/.

App Startup with __init__.py

A directory on disk can be turned into a Python package by containing an __init__.py file. Even if empty, this marks a directory as a Python package. We use __init__.py both as a package marker and to contain configuration code.

The generated development.ini file is read by paster which looks for the application module in the use variable of the app:tutorial section. The entry point is defined in the Setuptools configuration of this module, specifically in the setup.py file. For this tutorial, the entry point is defined as tutorial:main and points to the following main function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from pyramid.config import Configurator
from sqlalchemy import engine_from_config

from tutorial.models import initialize_sql

def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    engine = engine_from_config(settings, 'sqlalchemy.')
    initialize_sql(engine)
    config = Configurator(settings=settings)
    config.add_static_view('static', 'tutorial:static')
    config.add_route('home', '/', view='tutorial.views.my_view',
                     view_renderer='templates/mytemplate.pt')
    return config.make_wsgi_app()
  1. Lines 1-4. Imports to support later code.
  2. Line 9. Create a SQLAlchemy database engine from the sqlalchemy. prefixed settings in the development.ini file’s [app:tutorial] section. This will be a URI (something like sqlite://).
  3. Line 10. We initialize our SQL database using SQLAlchemy, passing it the engine
  4. Line 11. We construct a Configurator. settings is passed as a keyword argument with the dictionary values passed by PasteDeploy as the settings argument. This will be a dictionary of settings parsed by PasteDeploy, which contains deployment-related values such as reload_templates, db_string, etc.
  5. Line 12. We call pyramid.config.Configurator.add_static_view() with the arguments static (the name), and tutorial:static (the path). This registers a static resource view which will match any URL that starts with /static/. This will serve up static resources for us from within the static directory of our tutorial package, in this case, via http://localhost:6543/static/ and below. With this declaration, we’re saying that any URL that starts with /static should go to the static view; any remainder of its path (e.g. the /foo in /static/foo) will be used to compose a path to a static file resource, such as a CSS file.
  6. Lines 13-14. Register a route configuration via the pyramid.config.Configurator.add_route() method that will be used when the URL is /. Since this route has a pattern equalling / it is the “default” route. The argument named view with the value tutorial.views.my_view is the dotted name to a function we write (generated by the pyramid_routesalchemy template) that is given a request object and which returns a response or a dictionary. You will use pyramid.config.Configurator.add_route() statements in a URL dispatch based application to map URLs to code. This route also names a view_renderer, which is a template which lives in the templates subdirectory of the package. When the tutorial.views.my_view view returns a dictionary, a renderer will use this template to create a response.
  7. Line 15. We use the pyramid.config.Configurator.make_wsgi_app() method to return a WSGI application.

Content Models with models.py

In a SQLAlchemy-based application, a model object is an object composed by querying the SQL database which backs an application. SQLAlchemy is an “object relational mapper” (an ORM). The models.py file is where the pyramid_routesalchemy Paster template put the classes that implement our models.

Here is the source for models.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import transaction

from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import Unicode

from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker

from zope.sqlalchemy import ZopeTransactionExtension

DBSession = scoped_session(sessionmaker(
                             extension=ZopeTransactionExtension()))
Base = declarative_base()

class MyModel(Base):
    __tablename__ = 'models'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode(255), unique=True)
    value = Column(Integer)

    def __init__(self, name, value):
        self.name = name
        self.value = value

def populate():
    session = DBSession()
    model = MyModel(name=u'root',value=55)
    session.add(model)
    session.flush()
    transaction.commit()
    
def initialize_sql(engine):
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine
    Base.metadata.create_all(engine)
    try:
        populate()
    except IntegrityError:
        pass
  1. Lines 1-13. Imports to support later code.
  2. Line 15. We set up a SQLAlchemy “DBSession” object here. We specify that we’d like to use the “ZopeTransactionExtension”. This extension is an extension which allows us to use a transaction manager instead of controlling commits and aborts to database operations by hand.
  3. Line 16. We create a declarative Base object to use as a base class for our model.
  4. Lines 18-26. A model class named MyModel. It has an __init__ that takes a two arguments (name, and value). It stores these values as self.name and self.value within the __init__ function itself. The MyModel class also has a __tablename__ attribute. This informs SQLAlchemy which table to use to store the data representing instances of this class.
  5. Lines 28-33. A function named populate which adds a single model instance into our SQL storage and commits a transaction.
  6. Lines 35-42. A function named initialize_sql which receives a SQL database engine and binds it to our SQLAlchemy DBSession object. It also calls the populate function, to do initial database population.