3

I am attempting to implement Flask-Session in my python application. I read in the docs that its recommended to use another interface like the SqlAlchemySessionInterface instead of the default NullSessionInterface which is used when nothing is provided to the SESSION_TYPE configuration key.

From the flask_session/init.py file under class Session it reads

By default Flask-Session will use :class:NullSessionInterface, you really should configurate your app to use a different SessionInterface.

After setting the SESSION_TYPE configuration key to "sqlalchemy" I get an error

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) relation "sessions" does not exist

This indicates that Flask-Session is looking to use a table with the name "sessions" in my database model but I cannot find anywhere in the Flask-Session documentation where it points out that a table should be created and what fields it should have.

Can anyone suggest a solution to this please?

Ivan Kolesnikov
  • 1,787
  • 1
  • 29
  • 45
FlashspeedIfe
  • 368
  • 1
  • 6
  • 15
  • Did u resolve that problem? I can't find any solution... I created the table, but error still raising. Looks like the trouble is in schema, but I cant declare it for Session model without changing library code. In PG was set search_path to right schema, but it didnt help... – Jefferson Houp Jul 12 '18 at 11:59
  • @JeffersonHoup I was able to solve my problem and I described how I solved it in the answer on this thread. In the end though I ported my project to Django. Never again touching Flask for anything remotely serious. – FlashspeedIfe Jul 12 '18 at 20:43

2 Answers2

6

I wanted to use Flask-session, but I was also using Flask-migrate and didn't want to call db.create_all() manually and break the migration path. Fortunately, @Flashspeedlife's suggestion of just importing the Interface and instantiating it worked.

app/__init__.py:

from flask_session import SqlAlchemySessionInterface
from app.extensions import db, sess, migrate # My extensions file

def create_app():
    app = Flask(__name__)
    with app.app_context():
         db.init_app(app)
         migrate.init_app(app, db)

         sess.init_app(app)
         SqlAlchemySessionInterface(app, db, "sessions", "sess_")

Now, flask db migrate generates an alembic script with the new sessions table.

Nick K9
  • 3,885
  • 1
  • 29
  • 62
0

After studying the Flask-Session/init.py code I found that class SqlAlchemySessionInterface under its __init__ contains a Flask-SQLAlchemy model class Session(self.db.Model). To cause this table model to be created, in the file where I create my models I imported SqlAlchemySessionInterface from flask_sessionstore and put the line SqlAlchemySessionInterface(myApp, sqlAlchemyDbObject, "table_name", "prefix_") and then ran db.create_all().

class SqlAlchemySessionInterface(SessionInterface):
"""Uses the Flask-SQLAlchemy from a flask app as a session backend.

.. versionadded:: 0.2

:param app: A Flask app instance.
:param db: A Flask-SQLAlchemy instance.
:param table: The table name you want to use.
:param key_prefix: A prefix that is added to all store keys.
:param use_signer: Whether to sign the session id cookie or not.
:param permanent: Whether to use permanent session or not.
"""

serializer = pickle
session_class = SqlAlchemySession

def __init__(self, app, db, table, key_prefix, use_signer=False,
             permanent=True):
    if db is None:
        from flask_sqlalchemy import SQLAlchemy
        db = SQLAlchemy(app)
    self.db = db
    self.key_prefix = key_prefix
    self.use_signer = use_signer
    self.permanent = permanent

    class Session(self.db.Model):
        __tablename__ = table

        id = self.db.Column(self.db.Integer, primary_key=True)
        session_id = self.db.Column(self.db.String(255), unique=True)
        data = self.db.Column(self.db.LargeBinary)
        expiry = self.db.Column(self.db.DateTime)

        def __init__(self, session_id, data, expiry):
            self.session_id = session_id
            self.data = data
            self.expiry = expiry

        def __repr__(self):
            return '<Session data %s>' % self.data

    # self.db.create_all()
    self.sql_session_model = Session

I'am definitely using Django for my next project. Documentation for many Flask Extensions aren't great at all.

EDIT

Changed (imported SqlAlchemySessionInterface from flask_session) to (imported SqlAlchemySessionInterface from flask_sessionstore)

FlashspeedIfe
  • 368
  • 1
  • 6
  • 15
  • Where did you put the line `SqlAlchemySessionInterface(myApp, sqlAlchemyDbObject, "table_name", "prefix_")`? Do I understand correctly that you didn't need to create a new model for `table_name`? – Lewistrick Mar 22 '19 at 10:20
  • 2
    @Lewistrick I put that line in the `models.py` file. And yes yo do **not** need to create the model yourself. Importing the `SqlAlchemySessionInterface` from the `flask_sessionstore` together with calling `SqlAlchemySessionInterface()` will automatically create the `session` table. The exact line I used was `SqlAlchemySessionInterface(app, db, "session", "sess_")` – FlashspeedIfe Mar 22 '19 at 13:37