Home > database >  How to insert data with SQLAlchemy
How to insert data with SQLAlchemy

Time:11-04

I have trouble inserting data into a database with SQLAlchemy. I use scoped_session with a context manager (class implementation):

class Session:
    def __init__(self):
        pass

    def __enter__(self):
        engine = create_engine("sqlite:///test.db", echo = True)
        self.connection = engine.connect()
        self.session = scoped_session(\
                sessionmaker(\
                autocommit=True,\
                autoflush=False,\
                bind=engine))
        return self.session

    def __exit__(self, type, value, traceback):
        self.session.close()
        self.connection.close()

My inserting function:

def insert_value(a, b, c)
    with db_session() as db:
        db.add(Value(a = a, b = b, c = c))

The value is not properly added to the database even after the commit but for some reason, it works with a query().filter().update().

The db.add() doesn't produce any log and the documentation of SQLAlchemy is no help.

EDIT: The problem is with db.add() as select, update and delete operations are done through queries (e.g. db.query().all(), db.query().values() or db.query().delete()) and work fine.

EDIT 2: Some precision about how I instance the class and engine

Base = declarative_base()

class Value(Base):
    __tablename__ = "values"

    a = ...
    b = ...
    c = ...

Base.metadata.create_all(create_engine(...))

CodePudding user response:

https://docs.sqlalchemy.org/en/14/orm/session_transaction.html

Based on the above documentation, I guess autocommit has been deprecated. They have a session.begin() method now for auto commiting.

So you can use it this way:

with db_session.begin():
      foo

CodePudding user response:

I fixed the issue.

I think causes of the issue were:

  • the use of autocommit
  • I initiated an engine twice, once for the Session and once for the base classes.
engine = create_engine(...) // Initiated once and for all

Base = declarative_base()

class Value(Base):
    __tablename__ = "values"

    a = ...
    b = ...
    c = ...

Base.metadata.create_all(engine)

class DbSession:
    def __init__(self):
        pass

    def __enter__(self):
        self.connection = engine.connect() // Reuse the engine instead of creating a new one
        self.session = scoped_session(\
                sessionmaker(\
                autocommit=False,\
                autoflush=False,\
                bind=engine))
        return self.session

    def __exit__(self, type, value, traceback):
        self.session.commit()
        self.session.close()
        self.connection.close()


def insert_value(a, b, c):
    with DbSession() as db:
        db.add(Value(a = a, b = b, c = c))
  • Related