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
# your_app.py
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='./your_app.py'
export FLASK_DEBUG='true'
flask shell
>>> from your_app import db, User
>>> db.create_all()
>>> user = User(username='fooar', email='foo@bar.com')
>>> 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:
./your-project
├── app
│ ├── models
│ │ ├── __init__.py
│ │ └── user.py
│ ├── services
│ │ ├── __init__.py
│ │ ├── model_manager.py
│ │ └── user_manager.py
│ ├── __init__.py
│ ├── config.py
│ ├── extensions.py
│ └── factory.py
├── db
│ └── dev.sqlite
├── tests
│ ├── __init__.py
│ └── test_user.py
├── autoapp.py
└── setup.py
The entry point of our app will be autoapp.py, so let's take a look at that first:
# app/autoapp.py
import os
from app.factory import create_app
app = create_app(os.getenv('FLASK_ENV', 'development'))
And now the app factory:
# app/factory.py
from flask import Flask
from .config import DevConfig, ProdConfig, TestConfig
from .extensions import db
CONFIGS = {
'development': DevConfig,
'production': ProdConfig,
'test': TestConfig,
}
def create_app(env):
config = CONFIGS[env]
app = Flask(__name__,
template_folder=config.TEMPLATE_FOLDER,
static_folder=config.STATIC_FOLDER,
static_url_path=config.STATIC_URL_PATH)
app.config.from_object(config)
db.init_app(app)
return app
Which leads us to the config and extensions modules:
# app/config.py
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))
SQLALCHEMY_TRACK_MODIFICATIONS = False
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):
SQLALCHEMY_DATABASE_URI = \
'{engine}://{user}:{password}@{host}:{port}/{db_name}'.format(
engine='postgresql+psycopg2',
user=os.getenv('FLASK_DATABASE_USER', 'sqlalchemy_demo'),
password=os.getenv('FLASK_DATABASE_PASSWORD', 'sqlalchemy_demo'),
host=os.getenv('FLASK_DATABASE_HOST', '127.0.0.1'),
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/extensions.py
from flask_sqlalchemy_unchained import SQLAlchemyUnchained
db = SQLAlchemyUnchained()
The User model is the same as before:
# app/models/user.py
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/model_manager.py
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)
self.save(instance, 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)
self.save(instance, commit)
return instance
def delete(self, instance: db.Model, commit: bool = False) -> None:
db.session.delete(instance)
if commit:
self.commit()
def save(self, instance: db.Model, commit: bool = True):
db.session.add(instance)
if commit:
self.commit()
def commit(self) -> None:
db.session.commit()
def rollback(self) -> None:
db.session.rollback()
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/user_manager.py
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flask-sqlalchemy-unchained-0.7.2.tar.gz.
File metadata
- Download URL: flask-sqlalchemy-unchained-0.7.2.tar.gz
- Upload date:
- Size: 6.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.8.0 requests-toolbelt/0.8.0 tqdm/4.25.0 CPython/3.7.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea0659ec988459a43cebd833291d53eaee6b03a74dc1021e516267bece48f386
|
|
| MD5 |
1240dce151188dd344d9e3f5621d54fc
|
|
| BLAKE2b-256 |
67c905636e96066411887bed9bb4b040ae89b38656446c61b58e65730c198fdb
|
File details
Details for the file flask_sqlalchemy_unchained-0.7.2-py3-none-any.whl.
File metadata
- Download URL: flask_sqlalchemy_unchained-0.7.2-py3-none-any.whl
- Upload date:
- Size: 5.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.19.1 setuptools/40.8.0 requests-toolbelt/0.8.0 tqdm/4.25.0 CPython/3.7.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
292617dc9ddc46b2650b48d0934d304bc5c936c24bd9af3a01fea09ab77ff430
|
|
| MD5 |
4b36006e8af08129a0102eda0574d7e3
|
|
| BLAKE2b-256 |
575665805dc505090167b5b490c3cfa2ec86c337f019bb6e4abb3052d657a8f3
|