summaryrefslogtreecommitdiff
path: root/docs/source/databases.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/source/databases.rst')
-rw-r--r--docs/source/databases.rst191
1 files changed, 0 insertions, 191 deletions
diff --git a/docs/source/databases.rst b/docs/source/databases.rst
deleted file mode 100644
index 4eb5a9b..0000000
--- a/docs/source/databases.rst
+++ /dev/null
@@ -1,191 +0,0 @@
-.. _databases:
-
-Working with Databases, Transactions, and ORM's
-===============================================
-
-Pecan provides no opinionated support for working with databases, but
-it's easy to hook into your ORM of choice. This article details best
-practices for integrating the popular Python ORM, SQLAlchemy_, into
-your Pecan project.
-
-.. _SQLAlchemy: http://sqlalchemy.org
-
-``init_model`` and Preparing Your Model
----------------------------------------
-
-Pecan's default quickstart project includes an empty stub directory
-for implementing your model as you see fit.
-
-::
-
- .
- └── test_project
- ├── app.py
- ├── __init__.py
- ├── controllers
- ├── model
- │   ├── __init__.py
- └── templates
-
-By default, this module contains a special method, :func:`init_model`.
-
-::
-
- from pecan import conf
-
- def init_model():
- """
- This is a stub method which is called at application startup time.
-
- If you need to bind to a parsed database configuration, set up tables
- or ORM classes, or perform any database initialization, this is the
- recommended place to do it.
-
- For more information working with databases, and some common recipes,
- see http://pecan.readthedocs.org/en/latest/databases.html
- """
- pass
-
-The purpose of this method is to determine bindings from your
-configuration file and create necessary engines, pools,
-etc. according to your ORM or database toolkit of choice.
-
-Additionally, your project's :py:mod:`model` module can be used to define
-functions for common binding operations, such as starting
-transactions, committing or rolling back work, and clearing a session.
-This is also the location in your project where object and relation
-definitions should be defined. Here's what a sample Pecan
-configuration file with database bindings might look like.
-
-::
-
- # Server Specific Configurations
- server = {
- ...
- }
-
- # Pecan Application Configurations
- app = {
- ...
- }
-
- # Bindings and options to pass to SQLAlchemy's ``create_engine``
- sqlalchemy = {
- 'url' : 'mysql://root:@localhost/dbname?charset=utf8&use_unicode=0',
- 'echo' : False,
- 'echo_pool' : False,
- 'pool_recycle' : 3600,
- 'encoding' : 'utf-8'
- }
-
-And a basic model implementation that can be used to configure and
-bind using SQLAlchemy.
-
-::
-
- from pecan import conf
- from sqlalchemy import create_engine, MetaData
- from sqlalchemy.orm import scoped_session, sessionmaker
-
- Session = scoped_session(sessionmaker())
- metadata = MetaData()
-
- def _engine_from_config(configuration):
- configuration = dict(configuration)
- url = configuration.pop('url')
- return create_engine(url, **configuration)
-
- def init_model():
- conf.sqlalchemy.engine = _engine_from_config(conf.sqlalchemy)
-
- def start():
- Session.bind = conf.sqlalchemy.engine
- metadata.bind = Session.bind
-
- def commit():
- Session.commit()
-
- def rollback():
- Session.rollback()
-
- def clear():
- Session.remove()
-
-Binding Within the Application
-------------------------------
-
-There are several approaches to wrapping your application's requests
-with calls to appropriate model function calls. One approach is WSGI
-middleware. We also recommend Pecan :ref:`hooks`. Pecan comes with
-:class:`~pecan.hooks.TransactionHook`, a hook which can be used to wrap
-requests in database transactions for you. To use it, simply include it in
-your project's ``app.py`` file and pass it a set of functions related to
-database binding.
-
-::
-
- from pecan import conf, make_app
- from pecan.hooks import TransactionHook
- from test_project import model
-
- app = make_app(
- conf.app.root,
- static_root = conf.app.static_root,
- template_path = conf.app.template_path,
- debug = conf.app.debug,
- hooks = [
- TransactionHook(
- model.start,
- model.start_read_only,
- model.commit,
- model.rollback,
- model.clear
- )
- ]
- )
-
-In the above example, on HTTP ``POST``, ``PUT``, and ``DELETE``
-requests, :class:`~pecan.hooks.TransactionHook` takes care of the transaction
-automatically by following these rules:
-
-#. Before controller routing has been determined, :func:`model.start`
- is called. This function should bind to the appropriate
- SQLAlchemy engine and start a transaction.
-
-#. Controller code is run and returns.
-
-#. If your controller or template rendering fails and raises an
- exception, :func:`model.rollback` is called and the original
- exception is re-raised. This allows you to rollback your database
- transaction to avoid committing work when exceptions occur in your
- application code.
-
-#. If the controller returns successfully, :func:`model.commit` and
- :func:`model.clear` are called.
-
-On idempotent operations (like HTTP ``GET`` and ``HEAD`` requests),
-:class:`~pecan.hooks.TransactionHook` handles transactions following different
-rules.
-
-#. ``model.start_read_only()`` is called. This function should bind
- to your SQLAlchemy engine.
-
-#. Controller code is run and returns.
-
-#. If the controller returns successfully, ``model.clear()`` is
- called.
-
-Also note that there is a useful :func:`~pecan.decorators.after_commit`
-decorator provided in :ref:`pecan_decorators`.
-
-Splitting Reads and Writes
---------------------------
-
-Employing the strategy above with :class:`~pecan.hooks.TransactionHook` makes
-it very simple to split database reads and writes based upon HTTP methods
-(i.e., GET/HEAD requests are read-only and would potentially be routed
-to a read-only database slave, while POST/PUT/DELETE requests require
-writing, and would always bind to a master database with read/write
-privileges). It's also possible to extend
-:class:`~pecan.hooks.TransactionHook` or write your own hook implementation for
-more refined control over where and when database bindings are called.