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:
import datetime
from flask import Flask
from peewee import *
from playhouse.flask_utils import FlaskDB
DATABASE = 'postgresql://postgres:password@localhost:5432/my_database'
app = Flask(__name__)
app.config.from_object(__name__)
db_wrapper = FlaskDB(app)
class User(db_wrapper.Model):
username = CharField(unique=True)
class Tweet(db_wrapper.Model):
user = ForeignKeyField(User, backref='tweets')
content = TextField()
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:
# Obtain a reference to the Peewee database instance.
peewee_db = db_wrapper.database
@app.route('/transfer-funds/', methods=['POST'])
def transfer_funds():
with peewee_db.atomic():
# ...
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
:
app = Flask(__name__)
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:
DATABASE = {
'name': 'my_app_db',
'engine': 'playhouse.pool.PooledPostgresqlDatabase',
'user': 'postgres',
'max_connections': 32,
'stale_timeout': 600,
}
app = Flask(__name__)
app.config.from_object(__name__)
wrapper = FlaskDB(app)
pooled_postgres_db = wrapper.database
Using a peewee Database
object:
peewee_db = PostgresqlExtDatabase('my_app')
app = Flask(__name__)
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:
db_wrapper = FlaskDB()
# Even though the database is not yet initialized, you can still use the
# `Model` property to create model classes.
class User(db_wrapper.Model):
username = CharField(unique=True)
def create_app():
app = Flask(__name__)
app.config['DATABASE'] = 'sqlite:////home/code/apps/my-database.db'
db_wrapper.init_app(app)
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: |
|
---|
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:
@app.route('/blog/<slug>/')
def post_detail(slug):
public_posts = Post.select().where(Post.published == True)
post = get_object_or_404(public_posts, (Post.slug == slug))
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: |
|
---|
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:
@app.route('/blog/')
def post_index():
public_posts = (Post
.select()
.where(Post.published == True)
.order_by(Post.timestamp.desc()))
return object_list(
'post_index.html',
query=public_posts,
context_variable='post_list',
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 thepage
GET
parameter.pagination
, aPaginatedQuery
instance.
class PaginatedQuery
(query_or_model, paginate_by[, page_var=’page’[, check_bounds=False]])
Parameters: |
|
---|
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 aSelectQuery
with the appropriateLIMIT
andOFFSET
clauses.If
check_bounds
was set toTrue
and the requested page contains no objects, then a 404 will be raised.