flask.py - Provide extensions for Flask-SQLAlchemy¶
See test_flask.py - Unit tests for ../pythonic_sqlalchemy_query/flask.py for usage and examples.
Imports¶
These are listed in the order prescribed by PEP 8.
Third-party imports¶
from sqlalchemy.ext.declarative import declarative_base
from flask import _app_ctx_stack
from flask_sqlalchemy import SQLAlchemy
from flask_sqlalchemy.model import Model, DefaultMeta
Local imports¶
from . import QueryMakerScopedSession, QueryMaker
Flask-SQLAlchemy customization¶
Create a SQLAlchemy class that includes the pythonic_sqlalchemy_query extension. In particular, it supports the following improvements over Flask-SQLAlchemy’s queries:
User['peter'].q.first()
as a shortcut forUser.query.filter_by(username='peter').first()
.db.session(User)['peter'].q.first()
as a shortcut todb.session.query(User).filter_by(username='peter').first()
.
To use: db = SQLAlchemyPythonicQuery(app)
instead of db = SQLAlchemy(app)
, as shown in test_flask.py - Unit tests for ../pythonic_sqlalchemy_query/flask.py.
Enable syntax such as Model[id]
for queries.
class QueryMakerFlaskDeclarativeMeta(DefaultMeta):
def __getitem__(cls, key):
Extract the session from the Flask-SQLAlchemy query attribute.
session = cls.query.session
Build a new query from here, since cls.query
has already invoked add_entity
on cls
.
return QueryMaker(cls, session.query())[key]
Then, use this in the Flask-SQLAlchemy session.
class SQLAlchemyPythonicQuery(SQLAlchemy):
Unlike the standard SQLAlchemy parameters, this does not allow the model_class
keyword argument.
def __init__(self, *args, **kwargs):
Provide a declarative_base model for Flask-SQLAlchemy. This is almost identical to code in flask_sqlalchemy.SQLAlchemy.make_declarartive_base
, but using our custom metaclass.
assert 'model_class' not in kwargs
kwargs['model_class'] = declarative_base(
cls=Model,
name='Model',
metadata=kwargs.get('metadata', None),
Use our custom metaclass.
metaclass=QueryMakerFlaskDeclarativeMeta
)
super(SQLAlchemyPythonicQuery, self).__init__(*args, **kwargs)
Enable syntax such as db.session(User)['peter']
. The only change from the Flask-SQLAlchemy v2.3.2 source: QueryMakerScopedSession
instead of orm.scoped_session
.
def create_scoped_session(self, options=None):
if options is None:
options = {}
scopefunc = options.pop('scopefunc', _app_ctx_stack.__ident_func__)
options.setdefault('query_cls', self.Query)
return QueryMakerScopedSession(
self.create_session(options), scopefunc=scopefunc
)