flasksqlalchemymarshmallowmarshmallow-sqlalchemy

Marshmallow-sqlalchemy AttributeError: 'DummySession' object has no attribute 'get' on schema.load()


I have the following schema:

from flask_marshmallow import Marshmallow

ma = Marshmallow(app)

class TicketSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        model = db_models.TicketModel
        load_instance = True

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            field.required = False

TicketModel is a sqlalchemy db model reflected with automap_base. The primary key of the table is the column TicketId. When I try to load a dictionary that contains the primary key:

data = {
       "TicketId" :"123"
    }
            
TicketSchema().load(data)

It gives me

File "/lib/python3.10/site-packages/marshmallow_sqlalchemy/load_instance_mixin.py", line 60, in get_instance
    return self.session.get(self.opts.model, filters)
AttributeError: 'DummySession' object has no attribute 'get'

But when I try to load data that has any other field defined in the schema, it works. This error only happens when I try to load a field that is defined as a Primary Key.

EDIT: I included the DDL of the table I am reflecting from the database and how the sqlalchemy model is set up.

CREATE TABLE Ticket (
    TicketId varchar(100) NOT NULL,
    Requestor varchar(20) NOT NULL,
    Description varchar(MAX) NULL,
    CONSTRAINT Tickets_Rules_PK PRIMARY KEY (TicketId)
);

and the sqlalchemy model:

from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy.ext.automap import automap_base

engine = create_engine(
    f'mssql+pymssql://{user_sql}:{password_sql}@db', echo=False)

metadata = MetaData(schema=Config.SCHEMA) # This is a string

# Define the list of table names to reflect
table_names = Config.TABLES_TO_REFLECT # This is a list of strings

# Reflect tables
tables = {table_name:Table(table_name, metadata, autoload_with=engine) for table_name in table_names}

# Automap base
Base = automap_base(metadata=metadata)
Base.prepare()

# Access the model from Base
TicketModel = Base.classes.Ticket

2nd EDIT Packages I am using:

marshmallow-sqlalchemy==1.0.0
SQLAlchemy==2.0.30
flask-marshmallow==1.2.1

Solution

  • It's not clear from the docs (or alternatively, it's implicitly assumed), but you need to supply a sqla_session session factory attribute to the schema's Meta inner class.

    ...
    from sqlalchemy import orm
    ...
    
    Session = orm.scoped_session(orm.sessionmaker(engine))
    ...
    
    class TicketSchema(ma.SQLAlchemyAutoSchema):
          class Meta:                                                                                                                                                
              sqla_session = Session # <- this                                                                               
              model = TicketModel                                                                                                                                    
              load_instance = True