summaryrefslogtreecommitdiff
path: root/docs/tutorials/bfgwiki2/basiclayout.rst
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-06-01 00:15:14 +0000
committerChris McDonough <chrism@agendaless.com>2009-06-01 00:15:14 +0000
commit6117c04a79d29b710391d95c5cce63358c5490fe (patch)
tree86ada0eee517b2a2ae53c51604d444e1183b30d0 /docs/tutorials/bfgwiki2/basiclayout.rst
parentc2dbab3e024be02c4246746f3d7d9dc5da9219d8 (diff)
downloadpyramid-6117c04a79d29b710391d95c5cce63358c5490fe.tar.gz
pyramid-6117c04a79d29b710391d95c5cce63358c5490fe.tar.bz2
pyramid-6117c04a79d29b710391d95c5cce63358c5490fe.zip
Keep useful stuff.
Diffstat (limited to 'docs/tutorials/bfgwiki2/basiclayout.rst')
-rw-r--r--docs/tutorials/bfgwiki2/basiclayout.rst129
1 files changed, 79 insertions, 50 deletions
diff --git a/docs/tutorials/bfgwiki2/basiclayout.rst b/docs/tutorials/bfgwiki2/basiclayout.rst
index 1ec10094e..7cf8274c8 100644
--- a/docs/tutorials/bfgwiki2/basiclayout.rst
+++ b/docs/tutorials/bfgwiki2/basiclayout.rst
@@ -2,9 +2,9 @@
Basic Layout
============
-The starter files generated by the ``bfg_zodb`` template are basic,
-but they provide a good orientation for the high-level patterns common
-to most :term:`traversal` -based BFG (and BFG with ZODB) projects.
+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 BFG projects.
``__init__.py``
---------------
@@ -16,9 +16,9 @@ directory as a Python package.
Configuration With ``configure.zcml``
--------------------------------------
-BFG uses a 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:
+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:
@@ -28,26 +28,29 @@ namespace. Our sample ZCML file looks like the following:
#. *Line 3*. Boilerplate, the comment explains.
-#. *Lines 6-9*. Register a ``<view>`` that is bound to a class.
- ``.views.my_view`` is a *function* we write (generated by the
- ``bfg_zodb`` template) that is given a ``context`` and a
- ``request`` and returns a response.
+#. *Lines 6-7*. Register a :term:`subscriber` that tears down the
+ SQLAlchemy connection after a request is finished.
- Since this ``<view>`` doesn't have a ``name`` attribute, it is the
- "default" view for that class.
+#. *Lines 9-12*. Register a ``<route>`` that will be used when the
+ URL is ``/``. Since this ``<view>`` has a blank ``name``
+ attribute, it is the "default" view. ``.views.my_view`` refers to a
+ *function* we write (generated by the ``bfg_routesalchemy``
+ template) that is given a ``context`` and a ``request`` and returns
+ a response.
-#. *Lines 11-15*. Register a view on the ``MyModels`` class that
- answers URL segments of ``static``. This is a view that will serve
- up static resources for us, in this case, at
+#. *Lines 14-17*. Register a ``<route>`` with a path that starts with
+ ``/static``, capturing the rest of the URL as ``subpath``. This is
+ a view that will serve up static resources for us, in this case, at
``http://localhost:6543/static/`` and below.
Content Models with ``models.py``
---------------------------------
-BFG often uses the word *model* when talking about content resources
-arranged in a hierarchical *model graph*. The ``models.py`` file is
-where the ``bfg_zodb`` Paster template put the classes that implement
-our models.
+In the context of a SQLAlchemy-based application, a *model* object is
+an object composed by quering the SQL database which backs an
+application. SQLAlchemy is an "object relational mapper" (an ORM).
+The ``models.py`` file is where the ``bfg_zodb`` Paster template put
+the classes that implement our models.
Here is the source for ``models.py``:
@@ -55,22 +58,36 @@ Here is the source for ``models.py``:
:linenos:
:language: py
-#. *Lines 3-4*. The ``MyModel`` class we referred to in the ZCML is
- implemented here. It is persistent (via PersistentMapping). The
- ``__parent__`` and ``__name__`` are important parts of the
- traversal protocol. By default, have these as ``None`` indicating
- that this is the :term:`root` object.
-
-#. *Lines 6-12*. ``appmaker`` is used to return the *application
- root* object. It is called on *every request* to the BFG
- application (it is essentially a :term:`root factory`). It also
- performs bootstrapping by *creating* an application root (inside
- the ZODB root object) if one does not already exist.
-
- 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.
+#. *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.
App Startup with ``run.py``
---------------------------
@@ -84,21 +101,33 @@ and its ``app`` function:
:linenos:
:language: py
-#. *Line 11*. After importing our application, get the ``appmaker``
- function described above.
-
-#. *Line 12*. Get the ZODB configuration from the ``tutorial.ini``
- file's ``[app:main]`` section. This will be a URI (something like
- ``file:///path/to/Data.fs``).
-
-#. Line *16*. We create a :term:`root factory` using the
- ``PersistentApplicationFinder`` helper class, passing it the
- ZODB URI and our appmaker.
-
-#. Line *17*. We use the ``repoze.bfg.router.make_app`` to return a
- :term:`WSGI` application. The ``make_app`` function takes the root
- factory (``get_root``), the *package* representing our application,
- and the keywords parsed by PasteDeploy.
+#. *Lines 1-5*. Imports to support later code.
+
+#. *Lines 7-11*. We define a ``Cleanup`` class which has a
+ ``__del__`` method (the method called at Python object
+ destruction), which calls a function.
+
+#. *Lines 13-15*. An event :term:`subscriber` which adds a
+ ``Cleanup`` instance to the WSGI environment as
+ ``tutorial.sasession``. As a result of registering this event
+ subscriber, when the WSGI environment is cleaned up, our database
+ connection will be removed.
+
+#. *Lines 17-24*. Get the database configuration string from the
+ ``tutorial.ini`` file's ``[app:sql]`` section. This will be a URI
+ (something like ``sqlite://``).
+
+#. Line *25*. We initialize our SQL database using SQLAlchemy, passing
+ it the db string.
+
+#. Line *26*. We use the ``repoze.bfg.router.make_app`` to return a
+ :term:`WSGI` application. The ``make_app`` function's first
+ parameter is the "root factory". Since this is a URL dispatch
+ application, the root factory is ``None`` (we don't do any
+ :term:`traversal` in this app. The second argument is the
+ *package* representing our application, and the third argument,
+ ``options`` is passed as a keyword argument. It contains a
+ dictionary of options parsed by PasteDeploy.
We'll later change ``run.py`` when we add :term:`authorization` to our
wiki application.