============ Basic Layout ============ The starter files generated by the ``bfg_routesalchemy`` template are basic, but they provide a good orientation for the high-level patterns common to most :term:`url dispatch` -based :mod:`repoze.bfg` projects. The source code for this tutorial stage can be browsed at `docs.repoze.org `_. ``__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. Configuration With ``configure.zcml`` -------------------------------------- :mod:`repoze.bfg` uses a configuration markup language syntactically the same as Zope's implementation of :term:`ZCML`, but using a different default XML namespace. Our sample ZCML file looks like the following: .. literalinclude:: src/basiclayout/tutorial/configure.zcml :linenos: :language: xml #. *Line 1*. The root ```` element, using the ``http://namespaces.repoze.org/bfg`` namespace. #. *Line 4*. Boilerplate, the comment explains. #. *Lines 6-7*. Register a :term:`subscriber` that tears down the SQLAlchemy connection after a request is finished. #. *Lines 9-13*. Register a ```` :term:`route configuration` that will be used when the URL is ``/``. Since this ```` has an empty ``path`` attribute, it is the "default" route. The attribute named ``view`` with the value ``.views.my_view`` is the dotted name to a *function* we write (generated by the ``bfg_routesalchemy`` template) that is given a ``request`` object and which returns a response or a dictionary. You will use mostly ```` statements in a :term:`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 ``.views.my_view`` view returns a dictionary, a :term:`renderer` will use this template to create a response. #. *Lines 15-18*. Register a ```` directive that will match any URL that starts with ``/static/``. This will serve up static resources for us, in this case, at ``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. 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 ``bfg_routesalchemy`` Paster template put the classes that implement our models. Here is the source for ``models.py``: .. literalinclude:: src/basiclayout/tutorial/models.py :linenos: :language: py #. *Lines 1-16*. Imports to support later code. #. *Line 18*. 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. #. *Line 20*. Set up a SQLAlchemy metadata object. #. *Lines 22-24*. A model class named ``Model``. It has an ``__init__`` that takes a single argument (``name``). It stores a single attribute named ``name``. #. *Lines 26-31*. A SQLAlchemy ``Table`` declaration named ``models_table`` which we'll use later to map onto our ``Model`` class. #. *Line 33*. We map our ``models_table`` table to our Models class here. This makes an association between the ``Model`` class and the ``models`` table in the database, as far as SQLAlchemy is concerned. #. *Lines 35-40*. A function named ``populate`` which adds a single model instance into our SQL storage and commits a transaction. #. *Lines 42-50*. A function named ``initialize_sql`` which sets up an actual SQL database and binds it to our SQLAlchemy DBSession object. It also calls the ``populate`` function, to do initial database population. .. _sql_tm2_cleanup: App Startup with ``run.py`` --------------------------- When you run the application using the ``paster`` command using the ``tutorial.ini`` generated config file, the application configuration points at an Setuptools *entry point* described as ``egg:tutorial#app``. In our application, because the application's ``setup.py`` file says so, this entry point happens to be the ``app`` function within the file named ``run.py``: .. literalinclude:: src/basiclayout/tutorial/run.py :linenos: :language: py #. *Lines 1-8*. Imports to support later code. #. *Lines 10-14*. An event :term:`subscriber` which performs cleanup at transaction boundaries. As a result of registering this event subscriber, after the current transaction is committed or aborted, our database connection will be removed. #. *Lines 22-25*. Get the database configuration string from the ``tutorial.ini`` file's ``[app:sql]`` section. This will be a URI (something like ``sqlite://``). #. Line *26*. We initialize our SQL database using SQLAlchemy, passing it the db string. #. *Line 27*. We construct a :term:`Configurator`. The first argument provided to the configurator is the :term:`root factory`, which is used by the :mod:`repoze.bfg` :term:`traversal` mechanism. Since this is a URL dispatch application, the root factory is ``None``. The second argument ``settings`` is passed as a keyword argument. It contains a dictionary of settings parsed by PasteDeploy. #. *Lines 28-31*. We then load a ZCML file to do application configuration, and use the :meth:`repoze.bfg.configuration.Configurator.make_wsgi_app` method to return a :term:`WSGI` application.