Framework Integration

For web applications, it is common to open a connection when a request isreceived, and to close the connection when the response is delivered. In thissection I will describe how to add hooks to your web app to ensure the databaseconnection is handled properly.

These steps will ensure that regardless of whether you’re using a simple SQLitedatabase, or a pool of multiple Postgres connections, peewee will handle theconnections correctly.

Note

Applications that receive lots of traffic may benefit from using aconnection pool to mitigate the cost of setting up andtearing down connections on every request.

Flask

Flask and peewee are a great combo and my go-to for projects of any size. Flaskprovides two hooks which we will use to open and close our db connection. We’llopen the connection when a request is received, then close it when the responseis returned.

  1. from flask import Flask
  2. from peewee import *
  3.  
  4. database = SqliteDatabase('my_app.db')
  5. app = Flask(__name__)
  6.  
  7. # This hook ensures that a connection is opened to handle any queries
  8. # generated by the request.
  9. @app.before_request
  10. def _db_connect():
  11. database.connect()
  12.  
  13. # This hook ensures that the connection is closed when we've finished
  14. # processing the request.
  15. @app.teardown_request
  16. def _db_close(exc):
  17. if not database.is_closed():
  18. database.close()

Django

While it’s less common to see peewee used with Django, it is actually very easyto use the two. To manage your peewee database connections with Django, theeasiest way in my opinion is to add a middleware to your app. The middlewareshould be the very first in the list of middlewares, to ensure it runs firstwhen a request is handled, and last when the response is returned.

If you have a django project named my_blog and your peewee database isdefined in the module my_blog.db, you might add the following middlewareclass:

  1. # middleware.py
  2. from my_blog.db import database # Import the peewee database instance.
  3.  
  4.  
  5. def PeeweeConnectionMiddleware(get_response):
  6. def middleware(request):
  7. database.connect()
  8. try:
  9. response = get_response(request)
  10. finally:
  11. if not database.is_closed():
  12. database.close()
  13. return response
  14. return middleware
  15.  
  16.  
  17. # Older Django < 1.10 middleware.
  18. class PeeweeConnectionMiddleware(object):
  19. def process_request(self, request):
  20. database.connect()
  21.  
  22. def process_response(self, request, response):
  23. if not database.is_closed():
  24. database.close()
  25. return response

To ensure this middleware gets executed, add it to your settings module:

  1. # settings.py
  2. MIDDLEWARE_CLASSES = (
  3. # Our custom middleware appears first in the list.
  4. 'my_blog.middleware.PeeweeConnectionMiddleware',
  5.  
  6. # These are the default Django 1.7 middlewares. Yours may differ,
  7. # but the important this is that our Peewee middleware comes first.
  8. 'django.middleware.common.CommonMiddleware',
  9. 'django.contrib.sessions.middleware.SessionMiddleware',
  10. 'django.middleware.csrf.CsrfViewMiddleware',
  11. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  12. 'django.contrib.messages.middleware.MessageMiddleware',
  13. )
  14.  
  15. # ... other Django settings ...

Bottle

I haven’t used bottle myself, but looking at the documentation I believe thefollowing code should ensure the database connections are properly managed:

  1. # app.py
  2. from bottle import hook #, route, etc, etc.
  3. from peewee import *
  4.  
  5. db = SqliteDatabase('my-bottle-app.db')
  6.  
  7. @hook('before_request')
  8. def _connect_db():
  9. db.connect()
  10.  
  11. @hook('after_request')
  12. def _close_db():
  13. if not db.is_closed():
  14. db.close()
  15.  
  16. # Rest of your bottle app goes here.

Web.py

See the documentation forapplication processors.

  1. db = SqliteDatabase('my_webpy_app.db')
  2.  
  3. def connection_processor(handler):
  4. db.connect()
  5. try:
  6. return handler()
  7. finally:
  8. if not db.is_closed():
  9. db.close()
  10.  
  11. app.add_processor(connection_processor)

Tornado

It looks like Tornado’s RequestHandler class implements two hooks which canbe used to open and close connections when a request is handled.

  1. from tornado.web import RequestHandler
  2.  
  3. db = SqliteDatabase('my_db.db')
  4.  
  5. class PeeweeRequestHandler(RequestHandler):
  6. def prepare(self):
  7. db.connect()
  8. return super(PeeweeRequestHandler, self).prepare()
  9.  
  10. def on_finish(self):
  11. if not db.is_closed():
  12. db.close()
  13. return super(PeeweeRequestHandler, self).on_finish()

In your app, instead of extending the default RequestHandler, now you canextend PeeweeRequestHandler.

Note that this does not address how to use peewee asynchronously with Tornadoor another event loop.

Wheezy.web

The connection handling code can be placed in a middleware.

  1. def peewee_middleware(request, following):
  2. db.connect()
  3. try:
  4. response = following(request)
  5. finally:
  6. if not db.is_closed():
  7. db.close()
  8. return response
  9.  
  10. app = WSGIApplication(middleware=[
  11. lambda x: peewee_middleware,
  12. # ... other middlewares ...
  13. ])

Thanks to GitHub user @tuukkamustonen for submitting this code.

Falcon

The connection handling code can be placed in a middleware component.

  1. import falcon
  2. from peewee import *
  3.  
  4. database = SqliteDatabase('my_app.db')
  5.  
  6. class PeeweeConnectionMiddleware(object):
  7. def process_request(self, req, resp):
  8. database.connect()
  9.  
  10. def process_response(self, req, resp, resource):
  11. if not database.is_closed():
  12. database.close()
  13.  
  14. application = falcon.API(middleware=[
  15. PeeweeConnectionMiddleware(),
  16. # ... other middlewares ...
  17. ])

Pyramid

Set up a Request factory that handles database connection lifetime as follows:

  1. from pyramid.request import Request
  2.  
  3. db = SqliteDatabase('pyramidapp.db')
  4.  
  5. class MyRequest(Request):
  6. def __init__(self, *args, **kwargs):
  7. super().__init__(*args, **kwargs)
  8. db.connect()
  9. self.add_finished_callback(self.finish)
  10.  
  11. def finish(self, request):
  12. if not db.is_closed():
  13. db.close()

In your application main() make sure MyRequest is used asrequest_factory:

  1. def main(global_settings, **settings):
  2. config = Configurator(settings=settings, ...)
  3. config.set_request_factory(MyRequest)

CherryPy

See Publish/Subscribe pattern.

  1. def _db_connect():
  2. db.connect()
  3.  
  4. def _db_close():
  5. if not db.is_closed():
  6. db.close()
  7.  
  8. cherrypy.engine.subscribe('before_request', _db_connect)
  9. cherrypy.engine.subscribe('after_request', _db_close)

Sanic

In Sanic, the connection handling code can be placed in the request andresponse middleware sanic middleware.

  1. # app.py
  2. @app.middleware('request')
  3. async def handle_request(request):
  4. db.connect()
  5.  
  6. @app.middleware('response')
  7. async def handle_response(request, response):
  8. if not db.is_closed():
  9. db.close()

FastAPI

Similar to Flask, FastAPI provides two event based hooks which we will use to open andclose our db connection. We’ll open the connection when a request is received,then close it when the response is returned.

  1. from fastapi import FastAPI
  2. from peewee import *
  3.  
  4. db = SqliteDatabase('my_app.db')
  5. app = FastAPI()
  6.  
  7. # This hook ensures that a connection is opened to handle any queries
  8. # generated by the request.
  9. @app.on_event("startup")
  10. def startup():
  11. db.connect()
  12.  
  13.  
  14. # This hook ensures that the connection is closed when we've finished
  15. # processing the request.
  16. @app.on_event("shutdown")
  17. def shutdown():
  18. if not db.is_closed():
  19. db.close()

Other frameworks

Don’t see your framework here? Please open a GitHub ticket and I’ll see about adding asection, or better yet, submit a documentation pull-request.