Flask-Sqlalchemy Documentation (2.X) : Release 2.4.4
Flask-Sqlalchemy Documentation (2.X) : Release 2.4.4
(2.x)
Release 2.4.4
Pallets
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
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
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.
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:
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:
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()
>>> 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
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:
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)
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
>>> 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:
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:
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
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:
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:
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:
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.
SQLALCHEMY_DATABASE_URI The database URI that should be used for the connection.
Examples:
• sqlite:////tmp/test.db
• mysql://username:password@server/db
2.3. Configuration 9
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4
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
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
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:
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.
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.
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)
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
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:
• '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'))
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.
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.
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:
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
>>> db.session.delete(me)
>>> db.session.commit()
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:
id username email
1 admin [email protected]
2 peter [email protected]
3 guest [email protected]
>>> User.query.filter(User.email.endswith('@example.com')).all()
[<User u'admin'>, <User u'guest'>]
>>> 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'>]
>>> User.query.get(1)
<User u'admin'>
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))
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).
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'
}
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)
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'}
)
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.
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.
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.
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)
db = SQLAlchemy(model_class=IdModel)
class User(db.Model):
name = db.Column(db.String)
class Employee(User):
title = db.Column(db.String)
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:
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):
...
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:
class GetOrQuery(BaseQuery):
def get_or(self, ident, default=None):
return self.get(ident) or default
db = SQLAlchemy(query_class=GetOrQuery)
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.
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.
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.
class CustomMeta(DefaultMeta):
def __init__(cls, name, bases, d):
# custom class setup 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
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.
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.
THREE
API REFERENCE
3.1 API
3.1.1 Configuration
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.
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
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
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.
3.1.3 Sessions
3.1.4 Utilities
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.
FOUR
ADDITIONAL INFORMATION
4.1 License
4.2 Changes
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
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
Released 2020-05-25
• Fix bad pagination when records are de-duped. #812
Released 2019-09-24
• Fix AttributeError when using multiple binds with polymorphic models. #651
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)
Released 2017-10-11
• Don’t mask the parent table for single-table inheritance models. (#561)
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)
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. Changes 29
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4
4.2. Changes 31
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4
f
flask_sqlalchemy, 21
33
Flask-SQLAlchemy Documentation (2.x), Release 2.4.4
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
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