The quickest and easiest way to build large web apps and APIs with Flask and SQLAlchemy
Project description
Flask Unchained
The quickest and easiest way to build large web apps and APIs with Flask and SQLAlchemy
Flask Unchained is a Flask extension, a pluggable application factory, and a set of mostly optional "bundles" that together create a modern, fully integrated, and highly customizable web framework for Flask and its extension ecosystem. Flask Unchained aims to stay true to the spirit and API of Flask, while making it significantly easier to quickly build large web apps and APIs with Flask and SQLAlchemy.
Flask Unchained introduces "bundles" to Flask: bundles are Python packages that integrate functionality with Flask, Flask Unchained, and other bundles. That could mean anything from integrating vanilla Flask extensions to being full-blown apps your app can integrate, customize, and extend (like say, a blog or web store). Unlike vanilla Flask extensions, bundles are both consistent and highly extensible and customizable. Once you figure out how something works in one bundle, it's the same in every other bundle. They are conceptually similar to Django's "apps", but I think you'll find bundles are even more powerful and flexible.
The architecture of how Flask Unchained and its bundles work is inspired by the Symfony Framework, which is awesome, aside from the fact that it isn't Python ;)
Features
- easy to start with and even easier to quickly grow your app
- clean, flexible, and declarative application structure that encourages good design patterns (no circular imports!)
- no integration headaches between supported libraries: everything just works
- as little boilerplate/plumbing as possible
- out-of-the-box support for testing with
pytest
andfactory_boy
- improved class-based views (controllers and resources)
- declarative routing (routes registered with the app can be decoupled from the defaults decorated on views)
- dependency injection of services and extensions (into just about anything you can wrap with a decorator)
- simple and consistent patterns for extending and/or overriding practically everything (e.g. configuration, views/controllers/resources, routes, templates, models, serializers, services, extensions, ...)
- your customizations are easily distributable as a standalone bundle (Python package), which itself then supports the same patterns for customization, ad infinitum
- out-of-the-box (mostly optional) integrations with:
- SQLAlchemy and Flask-Migrate (database ORM and migrations, optional). SQLAlchemy Unchained builds some "sugar" on top of SQLAlchemy to make the best ORM in existence even quicker and easier to use:
- models automatically get a primary key column, unless you define one yourself
- models are (optionally) automatically timestamped when they are created and updated
- super-simple polymorphic model class inheritance
- a unified API for creating, querying, updating and deleting models with the ModelManager service base class
- Flask-Login (user authentication and sessions management) and Flask-Principal (user authorization with permissions and roles)
- both session and token authentication are currently supported
- includes optional support for registration (with optional required email confirmation before account activation)
- optional change password and forgot password functionality
- Flask-Marshmallow (SQLAlchemy model serialization, optional)
- the API Bundle provides a RESTful API framework integrating Marshmallow Serializers (aka Schemas) and SQLAlchemy models using ModelResource
- work-in-progress support for OpenAPI (aka Swagger) docs, using ReDoc as the frontend
- Flask-GraphQL (GraphQL support, integrates Graphene with SQLAlchemy, optional)
- Flask-WTF (forms and CSRF protection, always enabled)
- Flask-Session (server-side sessions, optional)
- Celery (distributed task queue, optional)
- Flask-Mail (email sending support, optional)
- Flask-Admin (admin interface, optional)
- Flask-BabelEx (translations, always enabled but optional)
- pytest and factory_boy (testing framework)
- SQLAlchemy and Flask-Migrate (database ORM and migrations, optional). SQLAlchemy Unchained builds some "sugar" on top of SQLAlchemy to make the best ORM in existence even quicker and easier to use:
- You can use Flask Unchained as-is with its out-of-the-box "stack", or if you don't like those choices, then you can use a different set of Flask extensions. Flask Unchained is designed to be so flexible that you could even extend it to make your own works-out-of-the-box web framework for Flask.
What does it look like?
Hello World
A silly (more verbose than it needs to be) example looks about like this:
# project-root/app.py
import random
from flask_unchained import FlaskUnchained, AppBundle, Service, injectable
from flask_unchained import Controller, route, param_converter, url_for
from flask_unchained.pytest import HtmlTestClient
BUNDLES = ['flask_unchained.bundles.controller']
class App(AppBundle):
def before_init_app(self, app: FlaskUnchained) -> None:
pass
def after_init_app(self, app: FlaskUnchained) -> None:
pass
class RandomService(Service):
def get_name(self) -> str:
return random.choice(['Alice', 'Bob', 'Grace', 'Judy'])
class SiteController(Controller):
class Meta:
url_prefix = '/'
random_service: RandomService = injectable
@route('/')
@param_converter(name=str)
def index(self, name: str = None):
name = name or self.random_service.get_name()
return f'Hello {name} from Flask Unchained!'
class TestSiteController:
def test_index(self, client: HtmlTestClient):
r = client.get(url_for('site_controller.index', name='World'))
assert r.status_code == 200
assert r.html == 'Hello World from Flask Unchained!'
You can run it like so:
pip install "flask-unchained[dev]"
export UNCHAINED="app"
pytest app.py
flask urls
flask run
Going Big
A larger application structure might look about like this:
/home/user/dev/project-root
├── app # your app bundle package
│ ├── admins # Flask-Admin model admins
│ ├── commands # Click CLI groups/commands
│ ├── extensions # vanilla Flask extensions
│ ├── models # SQLAlchemy models
│ ├── fixtures # SQLAlchemy model fixtures (for seeding the dev db)
│ ├── serializers # Marshmallow serializers (aka schemas)
│ ├── services # dependency-injectable services
│ ├── tasks # Celery tasks
│ ├── templates # Jinja2 templates
│ ├── views # Controllers, Resources and views
│ ├── __init__.py
│ ├── config.py # app config
│ └── routes.py # declarative routes
├── assets # static assets to be handled by Webpack
│ ├── images
│ ├── scripts
│ └── styles
├── bundles # custom bundles and/or bundle extensions/overrides
│ └── security # a customized/extended Security Bundle
│ ├── models
│ ├── serializers
│ ├── services
│ ├── templates
│ └── __init__.py
├── db
│ └── migrations # Alembic (SQLAlchemy) migrations (generated by Flask-Migrate)
├── static # static assets (Webpack compiles to here, and Flask
│ # serves this folder at /static (by default))
├── templates # the top-level templates folder
├── tests # your pytest tests
├── webpack # Webpack configs
└── unchained_config.py # the Flask Unchained config
To learn how to build such an app, check out the official tutorial. (NOTE: The tutorial is still a work-in-progress.) You can also check out Flask Unchained React SPA
Documentation and Tutorial
The docs are on Read the Docs, as is the official tutorial.
NOTE: Some bundles are still a work-in-progress. Parts of the documentation need improvement or are missing. Some corners of the code are still alpha-quality. Things work for me, but there are probably a few bugs lurking, and some parts of the API are potentially subject to change.
Contributing
Contributions are more than welcome! This is a big project with a lot of different things that need doing. There's a TODO file in the project root, or if you've got an idea, open an issue or a PR and let's chat!
License
MIT
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
File details
Details for the file Flask-Unchained-0.9.0.tar.gz
.
File metadata
- Download URL: Flask-Unchained-0.9.0.tar.gz
- Upload date:
- Size: 308.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.0 CPython/3.7.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | dfd2307ab96643c24ae0b69b7c6a7403bf8db37ad4f3434bc0e31df7661d5e33 |
|
MD5 | cfeb4a2ad934a897230da567e0a87834 |
|
BLAKE2b-256 | bce2675a3f47511bef65b3e1c44385cfddd196e1e72011f64fc130cc98b4e8c2 |
File details
Details for the file Flask_Unchained-0.9.0-py3-none-any.whl
.
File metadata
- Download URL: Flask_Unchained-0.9.0-py3-none-any.whl
- Upload date:
- Size: 440.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.0 CPython/3.7.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | a462f6fea994a031876d18c7efc790c1fe9d143eb079e12568c65a66ebcb4abd |
|
MD5 | f8735bb4514e766faf0c9d4d7ed5dfbb |
|
BLAKE2b-256 | ba37a3d60278d2a81ac528cd8597136f6dd55d56a5e852163f65b1682e6a4ff8 |