0% found this document useful (0 votes)
150 views

Flask-Sqlalchemy Documentation (2.X) : Release 2.4.4

Uploaded by

Ryang Sohn
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
150 views

Flask-Sqlalchemy Documentation (2.X) : Release 2.4.4

Uploaded by

Ryang Sohn
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

Flask-SQLAlchemy Documentation

(2.x)
Release 2.4.4

Pallets

Dec 18, 2020


CONTENTS

1 Requirements 3

2 User Guide 5
2.1 Quickstart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Introduction into Contexts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Declaring Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.5 Select, Insert, Delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.6 Multiple Databases with Binds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.7 Signalling Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.8 Customizing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

3 API Reference 21
3.1 API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

4 Additional Information 27
4.1 License . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.2 Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

Python Module Index 33

Index 35

i
ii
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

Flask-SQLAlchemy is an extension for Flask that adds support for SQLAlchemy to your application. It aims to
simplify using SQLAlchemy with Flask by providing useful defaults and extra helpers that make it easier to accomplish
common tasks.
See the SQLAlchemy documentation to learn how to work with the ORM in depth. The following documentation is a
brief overview of the most common tasks, as well as the features specific to Flask-SQLAlchemy.

CONTENTS 1
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

2 CONTENTS
CHAPTER

ONE

REQUIREMENTS

Our Version Python Flask SQLAlchemy


2.x 2.7, 3.4+ 0.12+ 0.8+ or 1.0.10+ w/ Python 3.7
3.0+ (in dev) 2.7, 3.5+ 1.0+ 1.0+

3
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

4 Chapter 1. Requirements
CHAPTER

TWO

USER GUIDE

2.1 Quickstart

Flask-SQLAlchemy is fun to use, incredibly easy for basic applications, and readily extends for larger applications.
For the complete guide, checkout the API documentation on the SQLAlchemy class.

2.1.1 A Minimal Application

For the common case of having one Flask application all you have to do is to create your Flask application, load the
configuration of choice and then create the SQLAlchemy object by passing it the application.
Once created, that object then contains all the functions and helpers from both sqlalchemy and sqlalchemy.
orm. Furthermore it provides a class called Model that is a declarative base which can be used to declare models:

from flask import Flask


from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)

class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)

def __repr__(self):
return '<User %r>' % self.username

To create the initial database, just import the db object from an interactive Python shell and run the SQLAlchemy.
create_all() method to create the tables and database:

>>> from yourapplication import db


>>> db.create_all()

Boom, and there is your database. Now to create some users:

>>> from yourapplication import User


>>> admin = User(username='admin', email='[email protected]')
>>> guest = User(username='guest', email='[email protected]')

But they are not yet in the database, so let’s make sure they are:

5
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

>>> db.session.add(admin)
>>> db.session.add(guest)
>>> db.session.commit()

Accessing the data in database is easy as a pie:

>>> User.query.all()
[<User u'admin'>, <User u'guest'>]
>>> User.query.filter_by(username='admin').first()
<User u'admin'>

Note how we never defined a __init__ method on the User class? That’s because SQLAlchemy adds an implicit
constructor to all model classes which accepts keyword arguments for all its columns and relationships. If you decide
to override the constructor for any reason, make sure to keep accepting **kwargs and call the super constructor with
those **kwargs to preserve this behavior:

class Foo(db.Model):
# ...
def __init__(self, **kwargs):
super(Foo, self).__init__(**kwargs)
# do custom stuff

2.1.2 Simple Relationships

SQLAlchemy connects to relational databases and what relational databases are really good at are relations. As such,
we shall have an example of an application that uses two tables that have a relationship to each other:

from datetime import datetime

class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80), nullable=False)
body = db.Column(db.Text, nullable=False)
pub_date = db.Column(db.DateTime, nullable=False,
default=datetime.utcnow)

category_id = db.Column(db.Integer, db.ForeignKey('category.id'),


nullable=False)
category = db.relationship('Category',
backref=db.backref('posts', lazy=True))

def __repr__(self):
return '<Post %r>' % self.title

class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)

def __repr__(self):
return '<Category %r>' % self.name

First let’s create some objects:

6 Chapter 2. User Guide


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

>>> py = Category(name='Python')
>>> Post(title='Hello Python!', body='Python is pretty cool', category=py)
>>> p = Post(title='Snakes', body='Ssssssss')
>>> py.posts.append(p)
>>> db.session.add(py)

As you can see, there is no need to add the Post objects to the session. Since the Category is part of the session all
objects associated with it through relationships will be added too. It does not matter whether db.session.add()
is called before or after creating these objects. The association can also be done on either side of the relationship - so
a post can be created with a category or it can be added to the list of posts of the category.
Let’s look at the posts. Accessing them will load them from the database since the relationship is lazy-loaded, but you
will probably not notice the difference - loading a list is quite fast:

>>> py.posts
[<Post 'Hello Python!'>, <Post 'Snakes'>]

While lazy-loading a relationship is fast, it can easily become a major bottleneck when you end up triggering extra
queries in a loop for more than a few objects. For this case, SQLAlchemy lets you override the loading strategy on the
query level. If you wanted a single query to load all categories and their posts, you could do it like this:

>>> from sqlalchemy.orm import joinedload


>>> query = Category.query.options(joinedload('posts'))
>>> for category in query:
... print category, category.posts
<Category u'Python'> [<Post u'Hello Python!'>, <Post u'Snakes'>]

If you want to get a query object for that relationship, you can do so using with_parent(). Let’s exclude that post
about Snakes for example:

>>> Post.query.with_parent(py).filter(Post.title != 'Snakes').all()


[<Post 'Hello Python!'>]

2.1.3 Road to Enlightenment

The only things you need to know compared to plain SQLAlchemy are:
1. SQLAlchemy gives you access to the following things:
• all the functions and classes from sqlalchemy and sqlalchemy.orm
• a preconfigured scoped session called session
• the metadata
• the engine
• a SQLAlchemy.create_all() and SQLAlchemy.drop_all() methods to create and drop tables
according to the models.
• a Model baseclass that is a configured declarative base.
2. The Model declarative base class behaves like a regular Python class but has a query attribute attached that
can be used to query the model. (Model and BaseQuery)
3. You have to commit the session, but you don’t have to remove it at the end of the request, Flask-SQLAlchemy
does that for you.

2.1. Quickstart 7
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

2.2 Introduction into Contexts

If you are planning on using only one application you can largely skip this chapter. Just pass your application to the
SQLAlchemy constructor and you’re usually set. However if you want to use more than one application or create the
application dynamically in a function you want to read on.
If you define your application in a function, but the SQLAlchemy object globally, how does the latter learn about the
former? The answer is the init_app() function:

from flask import Flask


from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app():
app = Flask(__name__)
db.init_app(app)
return app

What it does is prepare the application to work with SQLAlchemy. However that does not now bind the
SQLAlchemy object to your application. Why doesn’t it do that? Because there might be more than one appli-
cation created.
So how does SQLAlchemy come to know about your application? You will have to setup an application context. If
you are working inside a Flask view function or a CLI command, that automatically happens. However, if you are
working inside the interactive shell, you will have to do that yourself (see Creating an Application Context).
If you try to perform database operations outside an application context, you will see the following error:
No application found. Either work inside a view function or push an application context.
In a nutshell, do something like this:

>>> from yourapp import create_app


>>> app = create_app()
>>> app.app_context().push()

Alternatively, use the with-statement to take care of setup and teardown:

def my_function():
with app.app_context():
user = db.User(...)
db.session.add(user)
db.session.commit()

Some functions inside Flask-SQLAlchemy also accept optionally the application to operate on:

>>> from yourapp import db, create_app


>>> db.create_all(app=create_app())

2.3 Configuration

The following configuration values exist for Flask-SQLAlchemy. Flask-SQLAlchemy loads these values from your
main Flask config which can be populated in various ways. Note that some of those cannot be modified after the
engine was created so make sure to configure as early as possible and to not modify them at runtime.

8 Chapter 2. User Guide


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

2.3.1 Configuration Keys

A list of configuration keys currently understood by the extension:

SQLALCHEMY_DATABASE_URI The database URI that should be used for the connection.
Examples:
• sqlite:////tmp/test.db
• mysql://username:password@server/db

SQLALCHEMY_BINDS A dictionary that maps bind keys to SQLAlchemy connec-


tion URIs. For more information about binds see Multiple
Databases with Binds.
SQLALCHEMY_ECHO If set to True SQLAlchemy will log all the statements issued
to stderr which can be useful for debugging.
SQLALCHEMY_RECORD_QUERIES Can be used to explicitly disable or enable query recording.
Query recording automatically happens in debug or testing
mode. See get_debug_queries() for more informa-
tion.
SQLALCHEMY_NATIVE_UNICODE Can be used to explicitly disable native unicode support. This
is required for some database adapters (like PostgreSQL on
some Ubuntu versions) when used with improper database
defaults that specify encoding-less databases.
Deprecated as of v2.4 and will be removed in v3.0.
SQLALCHEMY_POOL_SIZE The size of the database pool. Defaults to the engine’s default
(usually 5).
Deprecated as of v2.4 and will be removed in v3.0.
SQLALCHEMY_POOL_TIMEOUT Specifies the connection timeout in seconds for the pool.
Deprecated as of v2.4 and will be removed in v3.0.
SQLALCHEMY_POOL_RECYCLE Number of seconds after which a connection is automati-
cally recycled. This is required for MySQL, which removes
connections after 8 hours idle by default. Note that Flask-
SQLAlchemy automatically sets this to 2 hours if MySQL
is used. Some backends may use a different default timeout
value. For more information about timeouts see Timeouts.
Deprecated as of v2.4 and will be removed in v3.0.
SQLALCHEMY_MAX_OVERFLOW Controls the number of connections that can be created after
the pool reached its maximum size. When those additional
connections are returned to the pool, they are disconnected
and discarded.
Deprecated as of v2.4 and will be removed in v3.0.
SQLALCHEMY_TRACK_MODIFICATIONS If set to True, Flask-SQLAlchemy will track modifications
of objects and emit signals. The default is None, which en-
ables tracking but issues a warning that it will be disabled by
default in the future. This requires extra memory and should
be disabled if not needed.
SQLALCHEMY_ENGINE_OPTIONS A dictionary of keyword args to send to
create_engine(). See also engine_options
to SQLAlchemy.

New in version 0.8: The SQLALCHEMY_NATIVE_UNICODE, SQLALCHEMY_POOL_SIZE,


SQLALCHEMY_POOL_TIMEOUT and SQLALCHEMY_POOL_RECYCLE configuration keys were added.
New in version 0.12: The SQLALCHEMY_BINDS configuration key was added.

2.3. Configuration 9
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

New in version 0.17: The SQLALCHEMY_MAX_OVERFLOW configuration key was added.


New in version 2.0: The SQLALCHEMY_TRACK_MODIFICATIONS configuration key was added.
Changed in version 2.1: SQLALCHEMY_TRACK_MODIFICATIONS will warn if unset.
Changed in version 2.4: * SQLALCHEMY_ENGINE_OPTIONS configuration key was added. * Deprecated keys
• SQLALCHEMY_NATIVE_UNICODE
• SQLALCHEMY_POOL_SIZE
• SQLALCHEMY_POOL_TIMEOUT
• SQLALCHEMY_POOL_RECYCLE
• SQLALCHEMY_MAX_OVERFLOW
Changed in version 2.4.3: Deprecated SQLALCHEMY_COMMIT_ON_TEARDOWN.

2.3.2 Connection URI Format

For a complete list of connection URIs head over to the SQLAlchemy documentation under (Supported Databases).
This here shows some common connection strings.
SQLAlchemy indicates the source of an Engine as a URI combined with optional keyword arguments to specify
options for the Engine. The form of the URI is:

dialect+driver://username:password@host:port/database

Many of the parts in the string are optional. If no driver is specified the default one is selected (make sure to not
include the + in that case).
Postgres:

postgresql://scott:tiger@localhost/mydatabase

MySQL:

mysql://scott:tiger@localhost/mydatabase

Oracle:

oracle://scott:[email protected]:1521/sidname

SQLite (note that platform path conventions apply):

#Unix/Mac (note the four leading slashes)


sqlite:////absolute/path/to/foo.db
#Windows (note 3 leading forward slashes and backslash escapes)
sqlite:///C:\\absolute\\path\\to\\foo.db
#Windows (alternative using raw string)
r'sqlite:///C:\absolute\path\to\foo.db'

2.3.3 Using custom MetaData and naming conventions

You can optionally construct the SQLAlchemy object with a custom MetaData object. This allows you to, among
other things, specify a custom constraint naming convention in conjunction with SQLAlchemy 0.9.2 or higher. Doing

10 Chapter 2. User Guide


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

so is important for dealing with database migrations (for instance using alembic as stated here. Here’s an example, as
suggested by the SQLAlchemy docs:

from sqlalchemy import MetaData


from flask import Flask
from flask_sqlalchemy import SQLAlchemy

convention = {
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}

metadata = MetaData(naming_convention=convention)
db = SQLAlchemy(app, metadata=metadata)

For more info about MetaData, check out the official docs on it.

2.3.4 Timeouts

Certain database backends may impose different inactive connection timeouts, which interferes with Flask-
SQLAlchemy’s connection pooling.
By default, MariaDB is configured to have a 600 second timeout. This often surfaces hard to debug, production
environment only exceptions like 2013: Lost connection to MySQL server during query.
If you are using a backend (or a pre-configured database-as-a-service) with a lower connection timeout, it is recom-
mended that you set SQLALCHEMY_POOL_RECYCLE to a value less than your backend’s timeout.

2.4 Declaring Models

Generally Flask-SQLAlchemy behaves like a properly configured declarative base from the declarative exten-
sion. As such we recommend reading the SQLAlchemy docs for a full reference. However the most common use
cases are also documented here.
Things to keep in mind:
• The baseclass for all your models is called db.Model. It’s stored on the SQLAlchemy instance you have to
create. See Quickstart for more details.
• Some parts that are required in SQLAlchemy are optional in Flask-SQLAlchemy. For instance the table name
is automatically set for you unless overridden. It’s derived from the class name converted to lowercase and with
“CamelCase” converted to “camel_case”. To override the table name, set the __tablename__ class attribute.

2.4.1 Simple Example

A very simple example:

class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
(continues on next page)

2.4. Declaring Models 11


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

(continued from previous page)

def __repr__(self):
return '<User %r>' % self.username

Use Column to define a column. The name of the column is the name you assign it to. If you want to use a different
name in the table you can provide an optional first argument which is a string with the desired column name. Primary
keys are marked with primary_key=True. Multiple keys can be marked as primary keys in which case they
become a compound primary key.
The types of the column are the first argument to Column. You can either provide them directly or call them to further
specify them (like providing a length). The following types are the most common:

Integer an integer
String(size) a string with a maximum length (optional in some databases, e.g. PostgreSQL)
Text some longer unicode text
DateTime date and time expressed as Python datetime object.
Float stores floating point values
Boolean stores a boolean value
PickleType stores a pickled Python object
LargeBinary stores large arbitrary binary data

2.4.2 One-to-Many Relationships

The most common relationships are one-to-many relationships. Because relationships are declared before they are
established you can use strings to refer to classes that are not created yet (for instance if Person defines a relationship
to Address which is declared later in the file).
Relationships are expressed with the relationship() function. However the foreign key has to be separately
declared with the ForeignKey class:

class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
addresses = db.relationship('Address', backref='person', lazy=True)

class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), nullable=False)
person_id = db.Column(db.Integer, db.ForeignKey('person.id'),
nullable=False)

What does db.relationship() do? That function returns a new property that can do multiple things. In this
case we told it to point to the Address class and load multiple of those. How does it know that this will return more
than one address? Because SQLAlchemy guesses a useful default from your declaration. If you would want to have a
one-to-one relationship you can pass uselist=False to relationship().
Since a person with no name or an email address with no address associated makes no sense, nullable=False
tells SQLAlchemy to create the column as NOT NULL. This is implied for primary key columns, but it’s a good idea
to specify it for all other columns to make it clear to other people working on your code that you did actually want a
nullable column and did not just forget to add it.
So what do backref and lazy mean? backref is a simple way to also declare a new property on the Address
class. You can then also use my_address.person to get to the person at that address. lazy defines when
SQLAlchemy will load the data from the database:

12 Chapter 2. User Guide


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

• 'select' / True (which is the default, but explicit is better than implicit) means that SQLAlchemy will load
the data as necessary in one go using a standard select statement.
• 'joined' / False tells SQLAlchemy to load the relationship in the same query as the parent using a JOIN
statement.
• 'subquery' works like 'joined' but instead SQLAlchemy will use a subquery.
• 'dynamic' is special and can be useful if you have many items and always want to apply additional SQL
filters to them. Instead of loading the items SQLAlchemy will return another query object which you can
further refine before loading the items. Note that this cannot be turned into a different loading strategy when
querying so it’s often a good idea to avoid using this in favor of lazy=True. A query object equivalent to a
dynamic user.addresses relationship can be created using Address.query.with_parent(user)
while still being able to use lazy or eager loading on the relationship itself as necessary.
How do you define the lazy status for backrefs? By using the backref() function:

class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
addresses = db.relationship('Address', lazy='select',
backref=db.backref('person', lazy='joined'))

2.4.3 Many-to-Many Relationships

If you want to use many-to-many relationships you will need to define a helper table that is used for the relationship.
For this helper table it is strongly recommended to not use a model but an actual table:

tags = db.Table('tags',
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'), primary_key=True),
db.Column('page_id', db.Integer, db.ForeignKey('page.id'), primary_key=True)
)

class Page(db.Model):
id = db.Column(db.Integer, primary_key=True)
tags = db.relationship('Tag', secondary=tags, lazy='subquery',
backref=db.backref('pages', lazy=True))

class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)

Here we configured Page.tags to be loaded immediately after loading a Page, but using a separate query. This
always results in two queries when retrieving a Page, but when querying for multiple pages you will not get additional
queries.
The list of pages for a tag on the other hand is something that’s rarely needed. For example, you won’t need that list
when retrieving the tags for a specific page. Therefore, the backref is set to be lazy-loaded so that accessing it for the
first time will trigger a query to get the list of pages for that tag. If you need to apply further query options on that
list, you could either switch to the 'dynamic' strategy - with the drawbacks mentioned above - or get a query object
using Page.query.with_parent(some_tag) and then use it exactly as you would with the query object from
a dynamic relationship.

2.4. Declaring Models 13


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

2.5 Select, Insert, Delete

Now that you have declared models it’s time to query the data from the database. We will be using the model definitions
from the Quickstart chapter.

2.5.1 Inserting Records

Before we can query something we will have to insert some data. All your models should have a constructor, so make
sure to add one if you forgot. Constructors are only used by you, not by SQLAlchemy internally so it’s entirely up to
you how you define them.
Inserting data into the database is a three step process:
1. Create the Python object
2. Add it to the session
3. Commit the session
The session here is not the Flask session, but the Flask-SQLAlchemy one. It is essentially a beefed up version of a
database transaction. This is how it works:

>>> from yourapp import User


>>> me = User('admin', '[email protected]')
>>> db.session.add(me)
>>> db.session.commit()

Alright, that was not hard. What happens at what point? Before you add the object to the session, SQLAlchemy
basically does not plan on adding it to the transaction. That is good because you can still discard the changes. For
example think about creating the post at a page but you only want to pass the post to the template for preview rendering
instead of storing it in the database.
The add() function call then adds the object. It will issue an INSERT statement for the database but because the
transaction is still not committed you won’t get an ID back immediately. If you do the commit, your user will have an
ID:

>>> me.id
1

2.5.2 Deleting Records

Deleting records is very similar, instead of add() use delete():

>>> db.session.delete(me)
>>> db.session.commit()

2.5.3 Querying Records

So how do we get data back out of our database? For this purpose Flask-SQLAlchemy provides a query attribute
on your Model class. When you access it you will get back a new query object over all records. You can then use
methods like filter() to filter the records before you fire the select with all() or first(). If you want to go
by primary key you can also use get().
The following queries assume following entries in the database:

14 Chapter 2. User Guide


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

id username email
1 admin [email protected]
2 peter [email protected]
3 guest [email protected]

Retrieve a user by username:

>>> peter = User.query.filter_by(username='peter').first()


>>> peter.id
2
>>> peter.email
u'[email protected]'

Same as above but for a non existing username gives None:

>>> missing = User.query.filter_by(username='missing').first()


>>> missing is None
True

Selecting a bunch of users by a more complex expression:

>>> User.query.filter(User.email.endswith('@example.com')).all()
[<User u'admin'>, <User u'guest'>]

Ordering users by something:

>>> User.query.order_by(User.username).all()
[<User u'admin'>, <User u'guest'>, <User u'peter'>]

Limiting users:

>>> User.query.limit(1).all()
[<User u'admin'>]

Getting user by primary key:

>>> User.query.get(1)
<User u'admin'>

2.5.4 Queries in Views

If you write a Flask view function it’s often very handy to return a 404 error for missing entries. Because this is
a very common idiom, Flask-SQLAlchemy provides a helper for this exact purpose. Instead of get() one can use
get_or_404() and instead of first() first_or_404(). This will raise 404 errors instead of returning None:

@app.route('/user/<username>')
def show_user(username):
user = User.query.filter_by(username=username).first_or_404()
return render_template('show_user.html', user=user)

Also, if you want to add a description with abort(), you can use it as argument as well.

>>> User.query.filter_by(username=username).first_or_404(description='There is no
˓→data with {}'.format(username))

2.5. Select, Insert, Delete 15


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

2.6 Multiple Databases with Binds

Starting with 0.12 Flask-SQLAlchemy can easily connect to multiple databases. To achieve that it preconfigures
SQLAlchemy to support multiple “binds”.
What are binds? In SQLAlchemy speak a bind is something that can execute SQL statements and is usually a con-
nection or engine. In Flask-SQLAlchemy binds are always engines that are created for you automatically behind the
scenes. Each of these engines is then associated with a short key (the bind key). This key is then used at model
declaration time to assocate a model with a specific engine.
If no bind key is specified for a model the default connection is used instead (as configured by
SQLALCHEMY_DATABASE_URI).

2.6.1 Example Configuration

The following configuration declares three database connections. The special default one as well as two others named
users (for the users) and appmeta (which connects to a sqlite database for read only access to some data the application
provides internally):
SQLALCHEMY_DATABASE_URI = 'postgres://localhost/main'
SQLALCHEMY_BINDS = {
'users': 'mysqldb://localhost/users',
'appmeta': 'sqlite:////path/to/appmeta.db'
}

2.6.2 Creating and Dropping Tables

The create_all() and drop_all() methods by default operate on all declared binds, including the default one.
This behavior can be customized by providing the bind parameter. It takes either a single bind name, '__all__' to
refer to all binds or a list of binds. The default bind (SQLALCHEMY_DATABASE_URI) is named None:
>>> db.create_all()
>>> db.create_all(bind=['users'])
>>> db.create_all(bind='appmeta')
>>> db.drop_all(bind=None)

2.6.3 Referring to Binds

If you declare a model you can specify the bind to use with the __bind_key__ attribute:
class User(db.Model):
__bind_key__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)

Internally the bind key is stored in the table’s info dictionary as 'bind_key'. This is important to know because
when you want to create a table object directly you will have to put it in there:
user_favorites = db.Table('user_favorites',
db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
db.Column('message_id', db.Integer, db.ForeignKey('message.id')),
info={'bind_key': 'users'}
)

16 Chapter 2. User Guide


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

If you specified the __bind_key__ on your models you can use them exactly the way you are used to. The model
connects to the specified database connection itself.

2.7 Signalling Support

Connect to the following signals to get notified before and after changes are committed to the database. These changes
are only tracked if SQLALCHEMY_TRACK_MODIFICATIONS is enabled in the config.
New in version 0.10.
Changed in version 2.1: before_models_committed is triggered correctly.
Deprecated since version 2.1: This will be disabled by default in a future version.
models_committed
This signal is sent when changed models were committed to the database.
The sender is the application that emitted the changes. The receiver is passed the changes parameter with a
list of tuples in the form (model instance, operation).
The operation is one of 'insert', 'update', and 'delete'.
before_models_committed
This signal works exactly like models_committed but is emitted before the commit takes place.

2.8 Customizing

Flask-SQLAlchemy defines sensible defaults. However, sometimes customization is needed. There are various ways
to customize how the models are defined and interacted with.
These customizations are applied at the creation of the SQLAlchemy object and extend to all models derived from
its Model class.

2.8.1 Model Class

SQLAlchemy models all inherit from a declarative base class. This is exposed as db.Model in Flask-SQLAlchemy,
which all models extend. This can be customized by subclassing the default and passing the custom class to
model_class.
The following example gives every model an integer primary key, or a foreign key for joined-table inheritance.

Note: Integer primary keys for everything is not necessarily the best database design (that’s up to your project’s
requirements), this is only an example.

from flask_sqlalchemy import Model, SQLAlchemy


import sqlalchemy as sa
from sqlalchemy.ext.declarative import declared_attr, has_inherited_table

class IdModel(Model):
@declared_attr
def id(cls):
for base in cls.__mro__[1:-1]:
if getattr(base, '__table__', None) is not None:
(continues on next page)

2.7. Signalling Support 17


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

(continued from previous page)


type = sa.ForeignKey(base.id)
break
else:
type = sa.Integer

return sa.Column(type, primary_key=True)

db = SQLAlchemy(model_class=IdModel)

class User(db.Model):
name = db.Column(db.String)

class Employee(User):
title = db.Column(db.String)

2.8.2 Model Mixins

If behavior is only needed on some models rather than all models, use mixin classes to customize only those models.
For example, if some models should track when they are created or updated:

from datetime import datetime

class TimestampMixin(object):
created = db.Column(
db.DateTime, nullable=False, default=datetime.utcnow)
updated = db.Column(db.DateTime, onupdate=datetime.utcnow)

class Author(db.Model):
...

class Post(TimestampMixin, db.Model):


...

2.8.3 Query Class

It is also possible to customize what is available for use on the special query property of models. For example,
providing a get_or method:

from flask_sqlalchemy import BaseQuery, SQLAlchemy

class GetOrQuery(BaseQuery):
def get_or(self, ident, default=None):
return self.get(ident) or default

db = SQLAlchemy(query_class=GetOrQuery)

# get a user by id, or return an anonymous user instance


user = User.query.get_or(user_id, anonymous_user)

And now all queries executed from the special query property on Flask-SQLAlchemy models can use the get_or
method as part of their queries. All relationships defined with db.relationship (but not sqlalchemy.orm.
relationship()) will also be provided with this functionality.

18 Chapter 2. User Guide


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

It also possible to define a custom query class for individual relationships as well, by providing the query_class
keyword in the definition. This works with both db.relationship and sqlalchemy.relationship:

class MyModel(db.Model):
cousin = db.relationship('OtherModel', query_class=GetOrQuery)

Note: If a query class is defined on a relationship, it will take precedence over the query class attached to its
corresponding model.

It is also possible to define a specific query class for individual models by overriding the query_class class attribute
on the model:

class MyModel(db.Model):
query_class = GetOrQuery

In this case, the get_or method will be only availble on queries orginating from MyModel.query.

2.8.4 Model Metaclass

Warning: Metaclasses are an advanced topic, and you probably don’t need to customize them to achieve what
you want. It is mainly documented here to show how to disable table name generation.

The model metaclass is responsible for setting up the SQLAlchemy internals when defining model subclasses. Flask-
SQLAlchemy adds some extra behaviors through mixins; its default metaclass, DefaultMeta, inherits them all.
• BindMetaMixin: __bind_key__ is extracted from the class and applied to the table. See Multiple
Databases with Binds.
• NameMetaMixin: If the model does not specify a __tablename__ but does specify a primary key, a name
is automatically generated.
You can add your own behaviors by defining your own metaclass and creating the declarative base yourself. Be sure
to still inherit from the mixins you want (or just inherit from the default metaclass).
Passing a declarative base class instead of a simple model base class, as shown above, to base_class will cause
Flask-SQLAlchemy to use this base instead of constructing one with the default metaclass.

from flask_sqlalchemy import SQLAlchemy


from flask_sqlalchemy.model import DefaultMeta, Model

class CustomMeta(DefaultMeta):
def __init__(cls, name, bases, d):
# custom class setup could go here

# be sure to call super


super(CustomMeta, cls).__init__(name, bases, d)

# custom class-only methods could go here

db = SQLAlchemy(model_class=declarative_base(
cls=Model, metaclass=CustomMeta, name='Model'))

You can also pass whatever other arguments you want to declarative_base() to customize the base class as
needed.

2.8. Customizing 19
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

Disabling Table Name Generation

Some projects prefer to set each model’s __tablename__ manually rather than relying on Flask-SQLAlchemy’s
detection and generation. The table name generation can be disabled by defining a custom metaclass.

from flask_sqlalchemy.model import BindMetaMixin, Model


from sqlalchemy.ext.declarative import DeclarativeMeta, declarative_base

class NoNameMeta(BindMetaMixin, DeclarativeMeta):


pass

db = SQLAlchemy(model_class=declarative_base(
cls=Model, metaclass=NoNameMeta, name='Model'))

This creates a base that still supports the __bind_key__ feature but does not generate table names.

20 Chapter 2. User Guide


CHAPTER

THREE

API REFERENCE

3.1 API

3.1.1 Configuration

class flask_sqlalchemy.SQLAlchemy(app=None, use_native_unicode=True, ses-


sion_options=None, metadata=None, query_class=<class
’flask_sqlalchemy.BaseQuery’>, model_class=<class
’flask_sqlalchemy.model.Model’>, engine_options=None)
This class is used to control the SQLAlchemy integration to one or more Flask applications. Depending on how
you initialize the object it is usable right away or will attach as needed to a Flask application.
There are two usage modes which work very similarly. One is binding the instance to a very specific Flask
application:

app = Flask(__name__)
db = SQLAlchemy(app)

The second possibility is to create the object once and configure the application later to support it:

db = SQLAlchemy()

def create_app():
app = Flask(__name__)
db.init_app(app)
return app

The difference between the two is that in the first case methods like create_all() and drop_all() will
work all the time but in the second case a flask.Flask.app_context() has to exist.
By default Flask-SQLAlchemy will apply some backend-specific settings to improve your experience with them.
As of SQLAlchemy 0.6 SQLAlchemy will probe the library for native unicode support. If it detects unicode
it will let the library handle that, otherwise do that itself. Sometimes this detection can fail in which case you
might want to set use_native_unicode (or the SQLALCHEMY_NATIVE_UNICODE configuration key)
to False. Note that the configuration key overrides the value you pass to the constructor. Direct support for
use_native_unicode and SQLALCHEMY_NATIVE_UNICODE are deprecated as of v2.4 and will be
removed in v3.0. engine_options and SQLALCHEMY_ENGINE_OPTIONS may be used instead.
This class also provides access to all the SQLAlchemy functions and classes from the sqlalchemy and
sqlalchemy.orm modules. So you can declare models like this:

21
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

class User(db.Model):
username = db.Column(db.String(80), unique=True)
pw_hash = db.Column(db.String(80))

You can still use sqlalchemy and sqlalchemy.orm directly, but note that Flask-SQLAlchemy customiza-
tions are available only through an instance of this SQLAlchemy class. Query classes default to BaseQuery
for db.Query, db.Model.query_class, and the default query_class for db.relationship and db.backref. If you use
these interfaces through sqlalchemy and sqlalchemy.orm directly, the default query class will be that of
sqlalchemy.

Check types carefully


Don’t perform type or isinstance checks against db.Table, which emulates Table behavior but is not a class.
db.Table exposes the Table interface, but is a function which allows omission of metadata.

The session_options parameter, if provided, is a dict of parameters to be passed to the session constructor.
See Session for the standard options.
The engine_options parameter, if provided, is a dict of parameters to be passed to create engine. See
create_engine() for the standard options. The values given here will be merged with and override anything
set in the 'SQLALCHEMY_ENGINE_OPTIONS' config variable or othewise set by this library.
New in version 0.10: The session_options parameter was added.
New in version 0.16: scopefunc is now accepted on session_options. It allows specifying a custom function
which will define the SQLAlchemy session’s scoping.
New in version 2.1: The metadata parameter was added. This allows for setting custom naming conventions
among other, non-trivial things.
The query_class parameter was added, to allow customisation of the query class, in place of the default of
BaseQuery.
The model_class parameter was added, which allows a custom model class to be used in place of Model.
Changed in version 2.1: Utilise the same query class across session, Model.query and Query.
New in version 2.4: The engine_options parameter was added.
Changed in version 2.4: The use_native_unicode parameter was deprecated.
Changed in version 2.4.3: COMMIT_ON_TEARDOWN is deprecated and will be removed in version 3.1. Call
db.session.commit() directly instead.
Query = None
Default query class used by Model.query and other queries. Customize this by passing query_class
to SQLAlchemy(). Defaults to BaseQuery.
apply_driver_hacks(app, sa_url, options)
This method is called before engine creation and used to inject driver specific hacks into the options. The
options parameter is a dictionary of keyword arguments that will then be used to call the sqlalchemy.
create_engine() function.
The default implementation provides some saner defaults for things like pool sizes for MySQL and sqlite.
Also it injects the setting of SQLALCHEMY_NATIVE_UNICODE.
create_all(bind=’__all__’, app=None)
Creates all tables.
Changed in version 0.12: Parameters were added

22 Chapter 3. API Reference


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

create_engine(sa_url, engine_opts)
Override this method to have final say over how the SQLAlchemy engine is created.
In most cases, you will want to use 'SQLALCHEMY_ENGINE_OPTIONS' config variable or set
engine_options for SQLAlchemy().
create_scoped_session(options=None)
Create a scoped_session on the factory from create_session().
An extra key 'scopefunc' can be set on the options dict to specify a custom scope function. If
it’s not provided, Flask’s app context stack identity is used. This will ensure that sessions are created and
removed with the request/response cycle, and should be fine in most cases.
Parameters options – dict of keyword arguments passed to session class in
create_session
create_session(options)
Create the session factory used by create_scoped_session().
The factory must return an object that SQLAlchemy recognizes as a session, or registering session events
may raise an exception.
Valid factories include a Session class or a sessionmaker.
The default implementation creates a sessionmaker for SignallingSession.
Parameters options – dict of keyword arguments passed to session class
drop_all(bind=’__all__’, app=None)
Drops all tables.
Changed in version 0.12: Parameters were added
engine
Gives access to the engine. If the database configuration is bound to a specific application (initialized with
an application) this will always return a database connection. If however the current application is used
this might raise a RuntimeError if no application is active at the moment.
get_app(reference_app=None)
Helper method that implements the logic to look up an application.
get_binds(app=None)
Returns a dictionary with a table->engine mapping.
This is suitable for use of sessionmaker(binds=db.get_binds(app)).
get_engine(app=None, bind=None)
Returns a specific engine.
get_tables_for_bind(bind=None)
Returns a list of all tables relevant for a bind.
init_app(app)
This callback can be used to initialize an application for the use with this database setup. Never use a
database in the context of an application not initialized that way or connections will leak.
make_connector(app=None, bind=None)
Creates the connector for a given state and bind.
make_declarative_base(model, metadata=None)
Creates the declarative base that all models will inherit from.
Parameters

3.1. API 23
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

• model – base model class (or a tuple of base classes) to pass to


declarative_base(). Or a class returned from declarative_base, in
which case a new base class is not created.
• metadata – MetaData instance to use, or none to use SQLAlchemy’s default.
metadata
The metadata associated with db.Model.
reflect(bind=’__all__’, app=None)
Reflects tables from the database.
Changed in version 0.12: Parameters were added

3.1.2 Models

class flask_sqlalchemy.Model
Base class for SQLAlchemy declarative base model.
To define models, subclass db.Model, not this class. To customize db.Model, subclass this and pass it as
model_class to SQLAlchemy.
__bind_key__
Optionally declares the bind to use. None refers to the default bind. For more information see Multiple
Databases with Binds.
__tablename__
The name of the table in the database. This is required by SQLAlchemy; however, Flask-SQLAlchemy
will set it automatically if a model has a primary key defined. If the __table__ or __tablename__
is set explicitly, that will be used instead.
class flask_sqlalchemy.BaseQuery(entities, session=None)
SQLAlchemy Query subclass with convenience methods for querying in a web application.
This is the default query object used for models, and exposed as Query. Override the query class for an
individual model by subclassing this and setting query_class.
first_or_404(description=None)
Like first() but aborts with 404 if not found instead of returning None.
get_or_404(ident, description=None)
Like get() but aborts with 404 if not found instead of returning None.
paginate(page=None, per_page=None, error_out=True, max_per_page=None)
Returns per_page items from page page.
If page or per_page are None, they will be retrieved from the request query. If max_per_page is
specified, per_page will be limited to that value. If there is no request or they aren’t in the query, they
default to 1 and 20 respectively.
When error_out is True (default), the following rules will cause a 404 response:
• No items are found and page is not 1.
• page is less than 1, or per_page is negative.
• page or per_page are not ints.
When error_out is False, page and per_page default to 1 and 20 respectively.
Returns a Pagination object.

24 Chapter 3. API Reference


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

3.1.3 Sessions

class flask_sqlalchemy.SignallingSession(db, autocommit=False, autoflush=True, **op-


tions)
The signalling session is the default session that Flask-SQLAlchemy uses. It extends the default session system
with bind selection and modification tracking.
If you want to use a different session you can override the SQLAlchemy.create_session() function.
New in version 2.0.
New in version 2.1: The binds option was added, which allows a session to be joined to an external transaction.
get_bind(mapper=None, clause=None)
Return the engine or connection for a given model or table, using the __bind_key__ if it is set.

3.1.4 Utilities

class flask_sqlalchemy.Pagination(query, page, per_page, total, items)


Internal helper class returned by BaseQuery.paginate(). You can also construct it from any other
SQLAlchemy query object if you are working with other libraries. Additionally it is possible to pass None
as query object in which case the prev() and next() will no longer work.
has_next
True if a next page exists.
has_prev
True if a previous page exists
items = None
the items for the current page
iter_pages(left_edge=2, left_current=2, right_current=5, right_edge=2)
Iterates over the page numbers in the pagination. The four parameters control the thresholds how many
numbers should be produced from the sides. Skipped page numbers are represented as None. This is how
you could render such a pagination in the templates:

{% macro render_pagination(pagination, endpoint) %}


<div class=pagination>
{%- for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
<a href="{{ url_for(endpoint, page=page) }}">{{ page }}</a>
{% else %}
<strong>{{ page }}</strong>
{% endif %}
{% else %}
<span class=ellipsis>...</span>
{% endif %}
{%- endfor %}
</div>
{% endmacro %}

next(error_out=False)
Returns a Pagination object for the next page.
next_num
Number of the next page

3.1. API 25
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

page = None
the current page number (1 indexed)
pages
The total number of pages
per_page = None
the number of items to be displayed on a page.
prev(error_out=False)
Returns a Pagination object for the previous page.
prev_num
Number of the previous page.
query = None
the unlimited query object that was used to create this pagination object.
total = None
the total number of items matching the query
flask_sqlalchemy.get_debug_queries()
In debug mode Flask-SQLAlchemy will log all the SQL queries sent to the database. This information is
available until the end of request which makes it possible to easily ensure that the SQL generated is the one
expected on errors or in unittesting. If you don’t want to enable the DEBUG mode for your unittests you can
also enable the query recording by setting the 'SQLALCHEMY_RECORD_QUERIES' config variable to True.
This is automatically enabled if Flask is in testing mode.
The value returned will be a list of named tuples with the following attributes:
statement The SQL statement issued
parameters The parameters for the SQL statement
start_time / end_time Time the query started / the results arrived. Please keep in mind that the timer function
used depends on your platform. These values are only useful for sorting or comparing. They do not
necessarily represent an absolute timestamp.
duration Time the query took in seconds
context A string giving a rough estimation of where in your application query was issued. The exact format is
undefined so don’t try to reconstruct filename or function name.

26 Chapter 3. API Reference


CHAPTER

FOUR

ADDITIONAL INFORMATION

4.1 License

Copyright 2010 Pallets


Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the follow-
ing disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, IN-
CIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSI-
NESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CON-
TRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAM-
AGE.

4.2 Changes

4.2.1 Version 2.4.4

Released 2020-07-14
• Change base class of meta mixins to type. This fixes an issue caused by a regression in CPython 3.8.4. #852

4.2.2 Version 2.4.3

Released 2020-05-26
• Deprecate SQLALCHEMY_COMMIT_ON_TEARDOWN as it can cause various design issues that are difficult to
debug. Call db.session.commit() directly instead. #216

27
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

4.2.3 Version 2.4.2

Released 2020-05-25
• Fix bad pagination when records are de-duped. #812

4.2.4 Version 2.4.1

Released 2019-09-24
• Fix AttributeError when using multiple binds with polymorphic models. #651

4.2.5 Version 2.4.0

Released 2019-04-24
• Make engine configuration more flexible. (#684)
• Address SQLAlchemy 1.3 deprecations. (#684)
• get_or_404() and first_or_404() now accept a description parameter to control the 404 mes-
sage. (#636)
• Use time.perf_counter for Python 3 on Windows. (#638)
• Drop support for Python 2.6 and 3.3. (#687)
• Add an example of Flask’s tutorial project, Flaskr, adapted for Flask-SQLAlchemy. (#720)

4.2.6 Version 2.3.2

Released 2017-10-11
• Don’t mask the parent table for single-table inheritance models. (#561)

4.2.7 Version 2.3.1

Released 2017-10-05
• If a model has a table name that matches an existing table in the metadata, use that table. Fixes a regression
where reflected tables were not picked up by models. (#551)
• Raise the correct error when a model has a table name but no primary key. (#556)
• Fix repr on models that don’t have an identity because they have not been flushed yet. (#555)
• Allow specifying a max_per_page limit for pagination, to avoid users specifying high values in the request
args. (#542)
• For paginate with error_out=False, the minimum value for page is 1 and per_page is 0. (#558)

28 Chapter 4. Additional Information


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

4.2.8 Version 2.3.0

Released 2017-09-28
• Multiple bugs with __tablename__ generation are fixed. Names will be generated for models that define
a primary key, but not for single-table inheritance subclasses. Names will not override a declared_attr.
PrimaryKeyConstraint is detected. (#541)
• Passing an existing declarative_base() as model_class to SQLAlchemy.__init__ will use this
as the base class instead of creating one. This allows customizing the metaclass used to construct the base.
(#546)
• The undocumented DeclarativeMeta internals that the extension uses for binds and table name generation
have been refactored to work as mixins. Documentation is added about how to create a custom metaclass that
does not do table name generation. (#546)
• Model and metaclass code has been moved to a new models module. _BoundDeclarativeMeta is re-
named to DefaultMeta; the old name will be removed in 3.0. (#546)
• Models have a default repr that shows the model name and primary key. (#530)
• Fixed a bug where using init_app would cause connectors to always use the current_app rather than the
app they were created for. This caused issues when multiple apps were registered with the extension. (#547)

4.2.9 Version 2.2

Released 2017-02-27, codename Dubnium


• Minimum SQLAlchemy version is 0.8 due to use of sqlalchemy.inspect.
• Added support for custom query_class and model_class as args to the SQLAlchemy constructor.
(#328)
• Allow listening to SQLAlchemy events on db.session. (#364)
• Allow __bind_key__ on abstract models. (#373)
• Allow SQLALCHEMY_ECHO to be a string. (#409)
• Warn when SQLALCHEMY_DATABASE_URI is not set. (#443)
• Don’t let pagination generate invalid page numbers. (#460)
• Drop support of Flask < 0.10. This means the db session is always tied to the app context and its teardown event.
(#461)
• Tablename generation logic no longer accesses class properties unless they are declared_attr. (#467)

4.2.10 Version 2.1

Released 2015-10-23, codename Caesium


• Table names are automatically generated in more cases, including subclassing mixins and abstract models.
• Allow using a custom MetaData object.
• Add support for binds parameter to session.

4.2. Changes 29
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

4.2.11 Version 2.0

Released 2014-08-29, codename Bohrium


• Changed how the builtin signals are subscribed to skip non-Flask-SQLAlchemy sessions. This will also fix the
attribute error about model changes not existing.
• Added a way to control how signals for model modifications are tracked.
• Made the SignallingSession a public interface and added a hook for customizing session creation.
• If the bind parameter is given to the signalling session it will no longer cause an error that a parameter is given
twice.
• Added working table reflection support.
• Enabled autoflush by default.
• Consider SQLALCHEMY_COMMIT_ON_TEARDOWN harmful and remove from docs.

4.2.12 Version 1.0

Released 2013-07-20, codename Aurum


• Added Python 3.3 support.
• Dropped 2.5 compatibility.
• Various bugfixes
• Changed versioning format to do major releases for each update now.

4.2.13 Version 0.16

• New distribution format (flask_sqlalchemy)


• Added support for Flask 0.9 specifics.

4.2.14 Version 0.15

• Added session support for multiple databases.

4.2.15 Version 0.14

• Make relative sqlite paths relative to the application root.

4.2.16 Version 0.13

• Fixed an issue with Flask-SQLAlchemy not selecting the correct binds.

30 Chapter 4. Additional Information


Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

4.2.17 Version 0.12

• Added support for multiple databases.


• Expose BaseQuery as db.Query.
• Set default query_class for db.relation, db.relationship, and db.dynamic_loader to
BaseQuery.
• Improved compatibility with Flask 0.7.

4.2.18 Version 0.11

• Fixed a bug introduced in 0.10 with alternative table constructors.

4.2.19 Version 0.10

• Added support for signals.


• Table names are now automatically set from the class name unless overridden.
• Model.query now always works for applications directly passed to the SQLAlchemy constructor. Further-
more the property now raises a RuntimeError instead of being None.
• Added session options to constructor.
• Fixed a broken __repr__.
• db.Table is now a factory function that creates table objects. This makes it possible to omit the metadata.

4.2.20 Version 0.9

• Applied changes to pass the Flask extension approval process.

4.2.21 Version 0.8

• Added a few configuration keys for creating connections.


• Automatically activate connection recycling for MySQL connections.
• Added support for the Flask testing mode.

4.2.22 Version 0.7

• Initial public release

4.2. Changes 31
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

32 Chapter 4. Additional Information


PYTHON MODULE INDEX

f
flask_sqlalchemy, 21

33
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

34 Python Module Index


INDEX

Symbols get_binds() (flask_sqlalchemy.SQLAlchemy


__bind_key__ (flask_sqlalchemy.Model attribute), 24 method), 23
__tablename__ (flask_sqlalchemy.Model attribute), get_debug_queries() (in module
24 flask_sqlalchemy), 26
get_engine() (flask_sqlalchemy.SQLAlchemy
A method), 23
apply_driver_hacks() get_or_404() (flask_sqlalchemy.BaseQuery method),
(flask_sqlalchemy.SQLAlchemy method), 24
22 get_tables_for_bind()
(flask_sqlalchemy.SQLAlchemy method),
B 23
BaseQuery (class in flask_sqlalchemy), 24
before_models_committed (built-in variable), 17
H
has_next (flask_sqlalchemy.Pagination attribute), 25
C has_prev (flask_sqlalchemy.Pagination attribute), 25
create_all() (flask_sqlalchemy.SQLAlchemy
method), 22 I
create_engine() (flask_sqlalchemy.SQLAlchemy init_app() (flask_sqlalchemy.SQLAlchemy method),
method), 22 23
create_scoped_session() items (flask_sqlalchemy.Pagination attribute), 25
(flask_sqlalchemy.SQLAlchemy method), iter_pages() (flask_sqlalchemy.Pagination method),
23 25
create_session() (flask_sqlalchemy.SQLAlchemy
method), 23 M
make_connector() (flask_sqlalchemy.SQLAlchemy
D method), 23
drop_all() (flask_sqlalchemy.SQLAlchemy method), make_declarative_base()
23 (flask_sqlalchemy.SQLAlchemy method),
23
E metadata (flask_sqlalchemy.SQLAlchemy attribute), 24
engine (flask_sqlalchemy.SQLAlchemy attribute), 23 Model (class in flask_sqlalchemy), 24
models_committed (built-in variable), 17
F
first_or_404() (flask_sqlalchemy.BaseQuery N
method), 24 next() (flask_sqlalchemy.Pagination method), 25
flask_sqlalchemy (module), 21 next_num (flask_sqlalchemy.Pagination attribute), 25

G P
get_app() (flask_sqlalchemy.SQLAlchemy method), page (flask_sqlalchemy.Pagination attribute), 25
23 pages (flask_sqlalchemy.Pagination attribute), 26
get_bind() (flask_sqlalchemy.SignallingSession paginate() (flask_sqlalchemy.BaseQuery method), 24
method), 25 Pagination (class in flask_sqlalchemy), 25

35
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4

per_page (flask_sqlalchemy.Pagination attribute), 26


prev() (flask_sqlalchemy.Pagination method), 26
prev_num (flask_sqlalchemy.Pagination attribute), 26

Q
query (flask_sqlalchemy.Pagination attribute), 26
Query (flask_sqlalchemy.SQLAlchemy attribute), 22

R
reflect() (flask_sqlalchemy.SQLAlchemy method),
24

S
SignallingSession (class in flask_sqlalchemy), 25
SQLAlchemy (class in flask_sqlalchemy), 21

T
total (flask_sqlalchemy.Pagination attribute), 26

36 Index

You might also like