Flask Utils

The playhouse.flask_utils module contains several helpers for integrating peewee with the Flask web framework.

Database Wrapper

The FlaskDB class is a wrapper for configuring and referencing a Peewee database from within a Flask application. Don’t let it’s name fool you: it is not the same thing as a peewee database. FlaskDB is designed to remove the following boilerplate from your flask app:

  • Dynamically create a Peewee database instance based on app config data.
  • Create a base class from which all your application’s models will descend.
  • Register hooks at the start and end of a request to handle opening and closing a database connection.

Basic usage:

  1. import datetime
  2. from flask import Flask
  3. from peewee import *
  4. from playhouse.flask_utils import FlaskDB
  5. DATABASE = 'postgresql://postgres:password@localhost:5432/my_database'
  6. app = Flask(__name__)
  7. app.config.from_object(__name__)
  8. db_wrapper = FlaskDB(app)
  9. class User(db_wrapper.Model):
  10. username = CharField(unique=True)
  11. class Tweet(db_wrapper.Model):
  12. user = ForeignKeyField(User, backref='tweets')
  13. content = TextField()
  14. timestamp = DateTimeField(default=datetime.datetime.now)

The above code example will create and instantiate a peewee PostgresqlDatabase specified by the given database URL. Request hooks will be configured to establish a connection when a request is received, and automatically close the connection when the response is sent. Lastly, the FlaskDB class exposes a FlaskDB.Model property which can be used as a base for your application’s models.

Here is how you can access the wrapped Peewee database instance that is configured for you by the FlaskDB wrapper:

  1. # Obtain a reference to the Peewee database instance.
  2. peewee_db = db_wrapper.database
  3. @app.route('/transfer-funds/', methods=['POST'])
  4. def transfer_funds():
  5. with peewee_db.atomic():
  6. # ...
  7. return jsonify({'transfer-id': xid})

Note

The actual peewee database can be accessed using the FlaskDB.database attribute.

Here is another way to configure a Peewee database using FlaskDB:

  1. app = Flask(__name__)
  2. db_wrapper = FlaskDB(app, 'sqlite:///my_app.db')

While the above examples show using a database URL, for more advanced usages you can specify a dictionary of configuration options, or simply pass in a peewee Database instance:

  1. DATABASE = {
  2. 'name': 'my_app_db',
  3. 'engine': 'playhouse.pool.PooledPostgresqlDatabase',
  4. 'user': 'postgres',
  5. 'max_connections': 32,
  6. 'stale_timeout': 600,
  7. }
  8. app = Flask(__name__)
  9. app.config.from_object(__name__)
  10. wrapper = FlaskDB(app)
  11. pooled_postgres_db = wrapper.database

Using a peewee Database object:

  1. peewee_db = PostgresqlExtDatabase('my_app')
  2. app = Flask(__name__)
  3. db_wrapper = FlaskDB(app, peewee_db)

Database with Application Factory

If you prefer to use the application factory pattern, the FlaskDB class implements an init_app() method.

Using as a factory:

  1. db_wrapper = FlaskDB()
  2. # Even though the database is not yet initialized, you can still use the
  3. # `Model` property to create model classes.
  4. class User(db_wrapper.Model):
  5. username = CharField(unique=True)
  6. def create_app():
  7. app = Flask(__name__)
  8. app.config['DATABASE'] = 'sqlite:////home/code/apps/my-database.db'
  9. db_wrapper.init_app(app)
  10. return app

Query utilities

The flask_utils module provides several helpers for managing queries in your web app. Some common patterns include:

get_object_or_404(query_or_model, \query*)

Parameters:
  • query_or_model – Either a Model class or a pre-filtered SelectQuery.
  • query – An arbitrarily complex peewee expression.

Retrieve the object matching the given query, or return a 404 not found response. A common use-case might be a detail page for a weblog. You want to either retrieve the post matching the given URL, or return a 404.

Example:

  1. @app.route('/blog/<slug>/')
  2. def post_detail(slug):
  3. public_posts = Post.select().where(Post.published == True)
  4. post = get_object_or_404(public_posts, (Post.slug == slug))
  5. return render_template('post_detail.html', post=post)

object_list(template_name, query[, context_variable=’object_list’[, paginate_by=20[, page_var=’page’[, check_bounds=True[, \*kwargs*]]]]])

Parameters:
  • template_name – The name of the template to render.
  • query – A SelectQuery instance to paginate.
  • context_variable – The context variable name to use for the paginated object list.
  • paginate_by – Number of objects per-page.
  • page_var – The name of the GET argument which contains the page.
  • check_bounds – Whether to check that the given page is a valid page. If check_bounds is True and an invalid page is specified, then a 404 will be returned.
  • kwargs – Arbitrary key/value pairs to pass into the template context.

Retrieve a paginated list of objects specified by the given query. The paginated object list will be dropped into the context using the given context_variable, as well as metadata about the current page and total number of pages, and finally any arbitrary context data passed as keyword-arguments.

The page is specified using the page GET argument, e.g. /my-object-list/?page=3 would return the third page of objects.

Example:

  1. @app.route('/blog/')
  2. def post_index():
  3. public_posts = (Post
  4. .select()
  5. .where(Post.published == True)
  6. .order_by(Post.timestamp.desc()))
  7. return object_list(
  8. 'post_index.html',
  9. query=public_posts,
  10. context_variable='post_list',
  11. paginate_by=10)

The template will have the following context:

  • post_list, which contains a list of up to 10 posts.
  • page, which contains the current page based on the value of the page GET parameter.
  • pagination, a PaginatedQuery instance.

class PaginatedQuery(query_or_model, paginate_by[, page_var=’page’[, check_bounds=False]])

Parameters:
  • query_or_model – Either a Model or a SelectQuery instance containing the collection of records you wish to paginate.
  • paginate_by – Number of objects per-page.
  • page_var – The name of the GET argument which contains the page.
  • check_bounds – Whether to check that the given page is a valid page. If check_bounds is True and an invalid page is specified, then a 404 will be returned.

Helper class to perform pagination based on GET arguments.

  • get_page()

    Return the currently selected page, as indicated by the value of the page_var GET parameter. If no page is explicitly selected, then this method will return 1, indicating the first page.

  • get_page_count()

    Return the total number of possible pages.

  • get_object_list()

    Using the value of get_page(), return the page of objects requested by the user. The return value is a SelectQuery with the appropriate LIMIT and OFFSET clauses.

    If check_bounds was set to True and the requested page contains no objects, then a 404 will be raised.