expatriate
expatriate

Reputation: 71

Flask-sqlalchemy temporary session/context variable

I'm exposing an API that allows users to do various CRUD operations.

The underlying classes of my SQLAlchemy data model are derived from a single declarative base, which include a "insert_uuid" field that (as the name implies) should register the UUID of the user triggering every insert.

In every API call, I'd like to set a 'temporary' session/context/whatever variable that I can use to set a default value. However, without having to rely on Flask's request module, because this declarative base resides in a 'data package' that does not need Flask in any way.

I.e. something like:

db.session.set_variable(user-uuid='aaaa-bbbb-etc')
db.session.add(object1)
db.session.add(object2)
db.session.add(object3)
db.session.remove_variable(user-uuid)

I've looked at setting the execution option on the SQLAlchemy engine. However this is an immutable dict, initialized upon creating the engine.

def get_user_uuid(context):
    return context.engine.get_execution_options().get('user_uuid', None)

class BaseTableDefinition(object):
    insert_uuid = Column("insert_uuid", UUIDType(), default=get_user_uuid)
    ....

BaseTable = declarative_base(cls=BaseTableDefinition)

And then, upon initializing the engine:

engine = create_engine(self._cn_string, echo=False, execution_options={'user_uuid': 'aaaa-bbbb-etc'})

In a 'static' back-end with a single-user-per-engine setup this could work, but it does not for my API use case.

What's the best way to achieve the above in a flask-sqlalchemy context, ideally relying on some functionality of the underlying SQLAlchemy core?

Thanks!

Upvotes: 4

Views: 1824

Answers (1)

snakecharmerb
snakecharmerb

Reputation: 55599

SQLAlchemy sessions have an info attribute, a user-modifiable dictionary, so something like this would work:

db.session.info['user-uuid'] = 'aaaa-bbbb-etc'
db.session.add(object1)
db.session.add(object2)
db.session.add(object3)
db.session.info.pop('user-uuid')

Session and sessionmaker accept an info keyword argument to set the contents of the dictionary at creation time. To set the value dynamically at session creation time in Flask-SQLAlchemy you might want to subclass SQLALchemy and override / extend create_session or create_scoped_session.

Upvotes: 2

Related Questions