Skip to main content

Integrates SQLAlchemy Unchained with Flask

Project description

Flask SQLAlchemy Unchained

Integrates SQLAlchemy Unchained with Flask. This package is a very thin wrapper around Flask-SQLAlchemy, and in terms of registering the extension with Flask, everything is the same.

Basic Usage


from flask import Flask
from flask_sqlalchemy_unchained import SQLAlchemyUnchained

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
db = SQLAlchemyUnchained(app)

class User(db.Model):
    class Meta:
        repr = ('id', 'username', 'email')

    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

Now let's create the table and add a row:

export FLASK_APP='./'
export FLASK_DEBUG='true'
flask shell
>>> from your_app import db, User
>>> db.create_all()
>>> user = User(username='fooar', email='')
>>> db.session.add(user)
>>> db.session.commit()
>>> assert User.query.all() == [user]

Real-World Usage

Now let's take a look at using the application factory pattern. Our app's directory structure will look like this:

├── app
│   ├── models
│   │   ├──
│   │   └──
│   ├── services
│   │   ├──
│   │   ├──
│   │   └──
│   ├──
│   ├──
│   ├──
│   └──
├── db
│   └── dev.sqlite
├── tests
│   ├──
│   └──

The entry point of our app will be, so let's take a look at that first:

# app/

import os

from app.factory import create_app

app = create_app(os.getenv('FLASK_ENV', 'development'))

And now the app factory:

# app/
from flask import Flask

from .config import DevConfig, ProdConfig, TestConfig
from .extensions import db

    'development': DevConfig,
    'production': ProdConfig,
    'test': TestConfig,

def create_app(env):
    config = CONFIGS[env]

    app = Flask(__name__,


    return app

Which leads us to the config and extensions modules:

# app/

import os

class BaseConfig:
    DEBUG = os.getenv('FLASK_DEBUG', False)

    APP_ROOT = os.path.abspath(os.path.dirname(__file__))
    PROJECT_ROOT = os.path.abspath(os.path.join(APP_ROOT, os.pardir))


class DevConfig(BaseConfig):
    DEBUG = os.getenv('FLASK_DEBUG', True)

    db_path = os.path.join(BaseConfig.PROJECT_ROOT, 'db', 'dev.sqlite')
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + db_path

class ProdConfig(BaseConfig):
            user=os.getenv('FLASK_DATABASE_USER', 'sqlalchemy_demo'),
            password=os.getenv('FLASK_DATABASE_PASSWORD', 'sqlalchemy_demo'),
            host=os.getenv('FLASK_DATABASE_HOST', ''),
            port=os.getenv('FLASK_DATABASE_PORT', 5432),
            db_name=os.getenv('FLASK_DATABASE_NAME', 'sqlalchemy_demo'))

class TestConfig(BaseConfig):
    TESTING = True
    DEBUG = True

    SQLALCHEMY_DATABASE_URI = 'sqlite://'  # :memory:
# app/

from flask_sqlalchemy_unchained import SQLAlchemyUnchained

db = SQLAlchemyUnchained()

The User model is the same as before:

# app/models/

from app.extensions import db

class User(db.Model):
    class Meta:
        repr = ('id', 'username', 'email')

    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

Because SQLAlchemy uses the data-mapper pattern, it's best practice to use managers/services for dealing with interactions with the database. A good base to start from might look like this:

# app/services/

from typing import *

from app.extensions import db

class ModelManager:
    model: Type[db.Model]

    def create(self, commit: bool = False, **kwargs) -> db.Model:
        instance = self.model(**kwargs), commit)
        return instance

    def update(self, instance: db.Model, commit: bool = False,
               **kwargs) -> db.Model:
        for attr, value in kwargs.items():
            setattr(instance, attr, value), commit)
        return instance

    def delete(self, instance: db.Model, commit: bool = False) -> None:
        if commit:

    def save(self, instance: db.Model, commit: bool = True):
        if commit:

    def commit(self) -> None:

    def rollback(self) -> None:

    def get(self, id) -> db.Model:
        return db.session.query(self.model).get(int(id))

    def get_by(self, **kwargs) -> db.Model:
        return db.session.query(self.model).filter_by(**kwargs).first()

    def find_all(self) -> List[db.Model]:
        return db.session.query(self.model).all()

    def find_by(self, **kwargs) -> List[db.Model]:
        return db.session.query(self.model).filter_by(**kwargs).all()

And then the UserManager class would look like this:

# app/services/

from ..models import User

from .model_manager import ModelManager

class UserManager(ModelManager):
    model = User

    def create(self, username, email, **kwargs) -> User:
        return super().create(username=username, email=email, **kwargs)

user_manager = UserManager()

The full source code for this example app, including integrations with Flask-Migrate and Py-YAML-Fixtures, can be found on GitHub.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for flask-sqlalchemy-unchained, version 0.7.6
Filename, size File type Python version Upload date Hashes
Filename, size flask_sqlalchemy_unchained-0.7.6-py3-none-any.whl (5.5 kB) File type Wheel Python version py3 Upload date Hashes View
Filename, size flask-sqlalchemy-unchained-0.7.6.tar.gz (7.1 kB) File type Source Python version None Upload date Hashes View

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page