- Support Python 3.10+
- Support Flask 2.2+ and Flask 3.0
- support using the app bundle's config module as the
unchained_config
by setting theFLASK_APP
environment variable to the app bundle name - allow bundles to specify other bundles they depend on, and implement support for resolving the correct order to load bundles
- add a submit field to forms by default
- bump required SQLAlchemy version to 1.4
- automatically increment database migration version if SQLAlchemy Bundle is enabled
- fix auto-generated imports in db migrations requiring user app code
- move some more database code into sqlalchemy-unchained
- add support for specifying the model converter class for sqlalchemy forms
- default alembic migrations to
compare_type=True
- alias
ModelManager
onto thedb
extension - drop
MaterialiedView
- add
flask users create-superuser
command
- minor admin bundle bugfixes and improvements
- fix redirect when the next parameter is an url-encoded string
- add helper admin column_formatter functions for easily generating links to other admin views
- enable dependency injection on
ModelAdmin
- add
DateField
,DateTimeField
, andIntervalField
toAdminModelFieldConverter
- alias
ModelResource
onto the API extension
- use custom exceptions for loading
unchained_config
to avoid catching erroneous ImportErrors - automatically configure sending the
csrf_token
cookie whenWTF_CSRF_ENABLED
is set toTrue
- do not require the API bundle to be enabled to use the Security Bundle
- add compatibility with Flask-Session 0.4.0
- fix compatibility with Flask-WTF auto-population of form data on submit
- allow extensions to specify optional dependent extensions
- add compatibility with upcoming wtforms v3
- remove experimental
qtconsole
command
- convert to
pyproject.toml
- format code with
black
- fix security bundle salt configuration for itsdangerous 2.0+
- fix security bundle redirect vulnerability
- add shell readline completion (from Flask PR 3960)
- fix
BundleBlueprint.register
to work with Flask 2.0+ - fix compatibility with click 8.0+
- bump required flask-sqlalchemy-unchained version
- API bundle fixes and improvements
- upgrade Flask-Admin templates to bootstrap4
- add Admin-specific post login/logout redirect endpoints
- add default Model Admins for the User and Role models
- fix default config settings for
ADMIN_LOGIN_ENDPOINT
andADMIN_LOGOUT_ENDPOINT
- defer initialization of the Admin extension to fix template overriding
- do not register duplicate templates folder for single-module app bundle
- rename
User.active
toUser.is_active
for compatibility with Flask-Login v0.5
- experimental asyncio support by installing Quart
- major improvements to
AppFactory
andAppFactoryHook
- support single-file app bundles (just export the app bundle as
FLASK_APP
) - support using a custom subclass of
FlaskUnchained
usingAppFactory.APP_CLASS
- support using a custom subclass of
AppFactory
- support passing all kwargs to
Flask
by setting the same names upper-cased inunchained_config
- support automatic defaults for the Flask app kwargs
root_path
,template_folder
,static_folder
, andstatic_url_path
- support extending and overriding hooks with the same consistent object-oriented patterns
- support using a custom module name for
unchained_config
by setting theUNCHAINED_CONFIG
environment variable - make it possible to define multiple modules hooks should load from (excluding config and routes, as those only make sense to live inside a single module within bundles)
- very experimental: add
Bundle.default_load_from_module_name
to ease migration from single-file app bundles to individual modules for different types (ie grouped by base class)
- very experimental: add
- support single-file app bundles (just export the app bundle as
- set up automatic dependency injection on commands (use
from flask_unchained.cli import cli, click
and define command groups for your commands using@cli.group()
) - add
flask unchained config
command for listing the current config (optionally filtered by bundle) - add
flask unchained extensions
command for listing extensions discovered by the app - add
flask unchaiend services
command for listing services discovered by the app - alias
flask.abort
(werkzeug.exceptions.abort
) asflask_unchained.abort
- alias
flask_wtf.csrf.generate_csrf
asflask_unchained.generate_csrf
- alias
flask.Request
andflask.Response
intoflask_unchained
- support
Accept
headers for handling responses in the API bundle - allow customizing the endpoint prefix for controllers using
Controller.Meta.endpoint_prefix
- document the rest of SQLAlchemy's config options
- automatically discover services in the
services
andmanagers
modules of bundles - bump sqlalchemy-unchained to v0.11.0
- add compatibility with pytest 5
- fix grouping routes by which bundle they're from
- fix registration of resource method routes so the order is deterministic
- fix
ConfigureAppHook
to load configs from every bundle in the hierarchy, not just the top-most one - fix resolving extension initiation order to only happen once instead of twice
- fix passing explicit rule overrides to
routes.resource
- fix automatic endpoint names for resource routes using the default implementations for create/list/get/delete/patch/put
- fix using default url rule from view function when no explicit rule passed to
func
- fix
flask urls
command when no URLs found - make sure hooks don't resolve local proxies
- fix
ModelResource.Meta.url_prefix
to useMeta.model.__name__
instead of the resource's class name - allow using
AnonymousUser
as if it were a SQLAlchemy model in queries
- rename
flask_unchained.BaseService
toflask_unchained.Service
- rename
PROJECT_ROOT
toROOT_PATH
for consistency with upstreamFlask
- rename
Bundle.folder
toBundle.root_path
for consistency withFlask
- rename
Controller.Meta.template_folder_name
toController.Meta.template_folder
for consistency withFlask
AppFactory
is now aSingleton
that must be instantiated (ie changeAppFactory.create_app(env)
toAppFactory().create_app(env)
inwsgi.py
)- no longer automatically set up dependency injection on all the methods from classes (you can still decorate them manually with
unchained.inject()
, but the preferred approach is to use class attributes to define what to inject into classes) - default endpoint name for simple view functions is now just the function name
- rename Resource method name constants to reduce confusion with HTTP method names
- remove
AppBundleConfig.ROOT_PATH
andAppBundleConfig.APP_ROOT
as they didn't always work correctly (useBundleConfig.current_app.root_path
instead) - moved
flask_unchained.commands.utils.print_table
toflask_unchained.cli.print_table
- if using the API bundle, require
marshmallow>=3.0
,marshmallow-sqlalchemy>=0.23
, andflask-marshmallow>=0.12
- if using the SQLAlchemy bundle, require
sqlalchemy-unchained>=0.10
- CSRF protection is no longer enabled by default. To re-enable it:
from flask_unchained import BundleConfig, unchained, generate_csrf
class Config(BundleConfig):
SECRET_KEY = 'some-secret-key'
WTF_CSRF_ENABLED = True
class TestConfig(Config):
WTF_CSRF_ENABLED = False
@unchained.after_request
def set_csrf_token_cookie(response):
if response:
response.set_cookie('csrf_token', generate_csrf())
return response
- customizing bundle module locations changed:
class YourBundle(Bundle):
extensions_module_name = 'custom' # before
extensions_module_names = ['custom'] # after
services_module_name = 'custom' # before
services_module_names = ['custom'] # after
commands_module_name = 'custom' # before
commands_module_names = ['custom'] # after
blueprints_module_name = 'custom' # before
blueprints_module_names = ['custom'] # after
models_module_name = 'custom' # before
models_module_names = ['custom'] # after
admins_module_name = 'custom' # before
admins_module_names = ['custom'] # after
resources_module_name = 'custom' # before
model_resources_module_names = ['custom'] # after
serializers_module_name = 'custom' # before
model_serializers_module_names = ['custom'] # after
celery_tasks_module_name = 'custom' # before
celery_tasks_module_names = ['custom'] # after
graphene_queries_module_name = 'custom' # before
graphene_queries_module_names = ['custom'] # after
graphene_mutations_module_name = 'custom' # before
graphene_mutations_module_names = ['custom'] # after
graphene_types_module_name = 'custom' # before
graphene_types_module_names = ['custom'] # after
- move
Bundle
andAppBundle
into theflask_unchained.bundles
module - move
BundleBlueprint
into theflask_unchained.bundles.controller.bundle_blueprint
module - move
_DeferredBundleFunctions
intoflask_unchained.unchained
, rename it toDeferredBundleFunctions
- make a bunch more protected internal classes public
- make
_has_views
,_blueprint_names
,_static_folders
,is_top_bundle
and_has_hierarchy_name_conflicts
methods onBundle
properties - rename double-negative
reverse_mro
parameter forBundle._iter_class_hierarchy
tomro
- warn when identical routes are registered
- make
AppFactory
methodsload_bundles
,load_bundle
andis_bundle
classmethods - add a noop
ViewsHook
to consolidate logic for defining and loadingviews_module_names
- move
param_converter
into the controller bundle
- compatibility with
sqlalchemy-unchained >= 0.7.6
- bump required
alembic
version to 1.0.9, fixesimmutabledict is not defined
error
-
bump requirements
-
change behavior of
flask new project
command to use defaults unless--prompt
is given -
NOTE: broken with sqlalchemy bundle, must install alembic using:
pip install git+https://github.com/sqlalchemy/alembic.git@d46de05b8b3281a85e6b107ef3f3407e232eb9e9#egg=alembic
- NOTE: broken with sqlalchemy bundle, must install alembic using:
pip install git+https://github.com/sqlalchemy/alembic.git@d46de05b8b3281a85e6b107ef3f3407e232eb9e9#egg=alembic
- NOTE: broken with sqlalchemy bundle, must install alembic using:
pip install git+https://github.com/sqlalchemy/alembic.git@d46de05b8b3281a85e6b107ef3f3407e232eb9e9#egg=alembic
- support injecting current app config into services
- extend the
string
url parameter converter to supportupper=True/False
- add
ModelForm.make_instance
convenience method - fix
ModelForm.name
to returnbytes
- add
.gitignore
toflask new project
command - improve error message when no
config
module found in the app bundle
- do not generate
celery_app.py
for new projects without the celery bundle enabled - improve user warnings when mail bundle is enabled but lxml or beautifulsoup isn't installed
- bump required versions of py-meta-utils and sqlalchemy-unchained
- fix the project's registered name on PyPI so it doesn't contain spaces
- support multiple routing rules with the same endpoint per view function
- fix type error in dependency injection when comparing parameter values with string
- 🔥OAuth🔥 support with the new OAuth Bundle (many thanks to @chriamue!)
- 🔥GraphQL🔥 support with the new Graphene Bundle
- add support for specifying parameters to inject into classes as class attributes
- when using
unchained.inject()
on a class, or subclassing a class that supports automatic dependency injection, all non-dunderscore methods now support having dependencies injected - the
include
function used inroutes.py
now supports specifying the url prefix as the first argument - support distributing and loading database fixture files with/from bundles
- implement proper support for
ModelForm
(it now adds fields for columns by default)
- add a way for bundle configs to get access to the current app-under-construction
- make options in
app.config
accessible as attributes, egapp.config.SECRET_KEY
is now the same asapp.config['SECRET_KEY']
- apply any settings from the app bundle config not already present in
app.config
as defaults before loading bundles
- improve documentation of how Flask Unchained works
- update to py-meta-utils 0.7.4 and sqlalchemy-unchained 0.7.0
- update to marshmallow 2.16
- update to marshmallow-sqlalchemy 0.15
- move database fixture loading code into the
py_yaml_fixtures
package (which is now a bundle as of v0.4.0) - consolidate
unchained.get_extension_local_proxy
andunchained.get_service_local_proxy
into a single function,unchained.get_local_proxy
- rename
AppConfig
toBundleConfig
- rename the
SQLAlchemy
extension class toSQLAlchemyUnchained
- rename
flask_unchained.bundles.sqlalchemy.model_form
toflask_unchained.bundles.sqlalchemy.forms
- rename the Graphene Bundle's
QueryObjectType
toQueriesObjectType
andMutationObjectType
toMutationsObjectType
- rename the Security Bundle's
SecurityUtilsService.verify_and_update_password
method toverify_password
- (internal) descriptors, metaclasses, meta options, and meta option factories are now protected
- (internal) rename the
flask_unchained.app_config
module toflask_unchained.config
- (internal) remove the
Bundle.root_folder
descriptor as it made no sense (Bundle.folder
is the bundle package's root folder) - (internal) rename
ConfigPropertyMeta
toConfigPropertyMetaclass
- fix the
Api
extension so it only generates docs for model resources that are registered with the app - fix setting of
Route._controller_cls
when controllers extend another concrete controller with routes - fix
Bundle.static_url_path
descriptor - specify required minimum package versions in
setup.py
, and pin versions inrequirements.txt
- fix the
UnchainedModelRegistry.reset
method so it allows using factory_boy fromconftest.py
- fix the
flask celery
commands so that they gracefully terminate instead of leaving zombie processes running - fix
param_converter
to allowing converting models from optional query parameters - add support to graphene for working with SQLAlchemy BigInteger columns
- ship
_templates
folder with the distribution so that theflask new <tempate>
command works when Flask Unchained gets installed viapip
IMPORTANT: these releases are broken, use v0.6.6
- export
get_boolean_env
from coreflask_unchained
package - export
param_converter
from coreflask_unchained
package - fix discovery of user-app
tests._unchained_config
- improve the output of commands that display their information in a table
- improve the output of custom sqlalchemy types in generated migrations files
- improve the output of the Views column from the
flask urls
command - improve the
--order-by
option of theflask urls
command - rename command
flask db import_fixtures
toflask db import-fixtures
- add a
FlaskForm
base class extending :class:~flask_wtf.FlaskForm
that adds support for specifying the rendered field order - automatically set the
csrf_token
cookie on responses - override the
click
module to also support documenting arguments withhelp
- also make the default help options
-h
and--help
instead of just--help
- also make the default help options
- refactor the hook store to be a class attribute of the bundle the hook(s) belong to
- add an
env
attribute on theFlaskUnchained
app instance - make the
bundles
attribute on theUnchained
extension anAttrDict
- bundles are now instantiated instead of passing the classes around directly
- add default config options, making
DEBUG
andTESTING
unnecessary to set manually - add a
_name
attribute toFlaskForm
to automatically name forms when rendering them programmatically - add
get_extension_local_proxy
andget_service_local_proxy
methods to theUnchained
extension - add support for overriding static files from bundles
- minor refactor of the declarative routing for
Controller
andResource
classes- consolidate default route rule generation into the
Route
class - make it possible to override the
member_param
of aResource
with theresource
routes function
- consolidate default route rule generation into the
- add a
TEMPLATE_FILE_EXTENSION
option toAppConfig
that controllers will respect by default. Controllers can still set theirtemplate_file_extension
attribute to override the application-wide default. - implement missing
delete
routing function - preliminary support for customizing the generated unique member param
- fix setting of
Route._controller_cls
to automatically always happen - refactor the SQLAlchemy Bundle to split most of it out into its own package, so that it can be used on its own (without Flask).
- fix the resource url prefix descriptor to convert to kebab-case instead of snake-case
- rename
Controller.template_folder
toController.template_folder_name
- add
Controller.make_response
as an alias forflask.make_response
- convert attributes on
Controller
,Resource
, andModelResource
to beclass Meta
options - rename
_meta
toMeta
per py-meta-utils v0.3 - rename
ModelManager.find_all
toModelManager.all
andModelManager.find_by
toModelManager.filter_by
for consistency with theQuery
api - move instantiation of the
CSRFProtect
extension from the security bundle into the controller bundle, where it belongs, so that it always gets used - improve registration of request cycle functions meant to run only for a specific bundle blueprint
- update
BaseService
to use a MetaOptionsFactory - make the
ModelManager.model
class attribute a meta option - rename the
flask db drop --drop
option toflask db drop --force
to skip prompting - rename the
flask db reset --reset
option toflask db reset --force
to skip prompting - add
no_autoflush
toSessionManager
- include html templates in the distribution
- add bundles to the shell context
- export
FlaskUnchained
from the root package - export Flask's
current_app
from the root package - never register static assets routes with babel bundle
- integrate the admin bundle into the
flask_unchained
package - integrate the api bundle into the
flask_unchained
package - integrate the celery bundle into the
flask_unchained
package - integrate the mail bundle into the
flask_unchained
package - integrate the sqlalchemy bundle into the
flask_unchained
package - integrate the webpack bundle into the
flask_unchained
package
- fix tests when babel_bundle isn't loaded
- fix infinite recursion error when registering urls and blueprints with babel
- make
tests._unchained_config
optional ifunchained_config
exists - fix discovery of bundle views to include any bundle in the hierarchy with views
- subclass Flask to improve handling of adding blueprints and url rules in conjunction with the babel bundle
- rename
unchained.BUNDLES
tounchained.bundles
- fix naming of bundle static endpoints
- support loading bundles as the app bundle for development
- refactor the babel commands to work with both app and regular bundles
- fix discovery of tests._unchained_config module
- add
flask qtconsole
command - rename Bundle.iter_bundles to Bundle.iter_class_hierarchy
- add
cli_runner
pytest fixture for testing click commands - fix register commands hook to support overriding groups and commands
- support registering request hooks, template tags/filters/tests, and context processors via deferred decorators on the Unchained and Bundle classes
- ship the controller bundle, session bundle, and babel bundles as part of core
- the babel and controller bundles are now mandatory, and will be included automatically
- bugfix: Bundle.static_url_prefix renamed to Bundle.static_url_path
- bugfix: check for
FunctionType
inset_up_class_dependency_injection
- rename
BaseConfig
toConfig
- add utilities for dealing with optional dependencies:
OptionalClass
: generic base class that can also be used as a substitute for extensions that have base classes defined as attributes on themoptional_pytest_fixture
: allows to conditionally register test fixtures
- hooks now declare their dependencies by hook name, as opposed to using an integer priority
- early releases