diff --git a/docs/api/wuttaweb/db.rst b/docs/api/wuttaweb/db.rst new file mode 100644 index 0000000..b90e227 --- /dev/null +++ b/docs/api/wuttaweb/db.rst @@ -0,0 +1,6 @@ + +``wuttaweb.db`` +=============== + +.. automodule:: wuttaweb.db + :members: diff --git a/docs/api/wuttaweb/index.rst b/docs/api/wuttaweb/index.rst index 2e49d4b..1e8ab57 100644 --- a/docs/api/wuttaweb/index.rst +++ b/docs/api/wuttaweb/index.rst @@ -8,6 +8,7 @@ :maxdepth: 1 app + db handler helpers menus diff --git a/pyproject.toml b/pyproject.toml index 985bef5..baa0fed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ dependencies = [ "waitress", "WebHelpers2", "WuttJamaican[db]>=0.7.0", + "zope.sqlalchemy>=1.5", ] diff --git a/src/wuttaweb/app.py b/src/wuttaweb/app.py index 18b07fb..506bacc 100644 --- a/src/wuttaweb/app.py +++ b/src/wuttaweb/app.py @@ -31,6 +31,8 @@ from wuttjamaican.conf import make_config from pyramid.config import Configurator +import wuttaweb.db + class WebAppProvider(AppProvider): """ @@ -83,17 +85,21 @@ def make_wutta_config(settings): If this config file path cannot be discovered, an error is raised. """ - # initialize config and embed in settings dict, to make - # available for web requests later + # validate config file path path = settings.get('wutta.config') if not path or not os.path.exists(path): raise ValueError("Please set 'wutta.config' in [app:main] " "section of config to the path of your " "config file. Lame, but necessary.") + # make config per usual, add to settings wutta_config = make_config(path) - settings['wutta_config'] = wutta_config + + # configure database sessions + if hasattr(wutta_config, 'appdb_engine'): + wuttaweb.db.Session.configure(bind=wutta_config.appdb_engine) + return wutta_config diff --git a/src/wuttaweb/db.py b/src/wuttaweb/db.py new file mode 100644 index 0000000..32d2418 --- /dev/null +++ b/src/wuttaweb/db.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# wuttaweb -- Web App for Wutta Framework +# Copyright © 2024 Lance Edgar +# +# This file is part of Wutta Framework. +# +# Wutta Framework is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Wutta Framework is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# Wutta Framework. If not, see . +# +################################################################################ +""" +Database sessions for web app + +The web app uses a different database session than other +(e.g. console) apps. The web session is "registered" to the HTTP +request/response life cycle (aka. transaction) such that the session +is automatically rolled back on error, and automatically committed if +the response is finalized without error. + +.. class:: Session + + Primary database session class for the web app. + + Note that you often do not need to "instantiate" this session, and + can instead call methods directly on the class:: + + from wuttaweb.db import Session + + users = Session.query(model.User).all() + + However in certain cases you may still want/need to instantiate it, + e.g. when passing a "true/normal" session to other logic. But you + can always call instance methods as well:: + + from wuttaweb.db import Session + from some_place import some_func + + session = Session() + + # nb. assuming func does not expect a "web" session per se, pass instance + some_func(session) + + # nb. these behave the same (instance vs. class method) + users = session.query(model.User).all() + users = Session.query(model.User).all() +""" + +from sqlalchemy import orm +from zope.sqlalchemy.datamanager import register + + +Session = orm.scoped_session(orm.sessionmaker()) + +register(Session)