`'list' object has no attribute '_sa_adapter'`
Hey everyone!
I'm trying to persist a schema that has a one-to-many relationship. For example, I am persisting a 'product' that can have many 'categories'
I have defined the Schemas like so
from project import ma # global ma object
class CategorySchema(SQLAlchemyAutoSchema):
class Meta:
model = Category
fields = ('id', 'title')
include_fk = True
load_instance = True
id = ma.auto_field('id', hide=True)
title = ma.auto_field()
class ProductSchema(SQLAlchemyAutoSchema):
class Meta:
model = Product
fields = ('id', 'title', 'categories')
include_fk = True
load_instance = True
include_relationships = True
ordered = True
id = ma.auto_field('id', hide=True) # my own custom thing, hide isn't a feature of this lib
title = ma.auto_field()
categories = ma.List(ma.Nested(ProductCategorySchema))
Editing an item seems to work totally fine. (context: request_data is simply a dict with all required fields from the schema)
schema = ProductSchema()
existing_item = db.session.query(Product).filter(Product.id == item_id).first()
if existing_item is not None:
updated_item = schema.load(request_data, session=db.session, instance=existing_item)
db.session.commit()
Running the above code when changing how many categories are associated with the product works flawlessly. But when I try to create an object...
schema = ProductSchema()
new_item = schema.load(request_data, session=db.session, partial=True)
db.session.add(new_item)
db.session.commit()
It returns the following error:
'list' object has no attribute '_sa_adapter'
Further investigation revealed that when loading an existing instance, the categories are inside of an InstrumentedList, whereas attempting to create a product with many, existing categories, creates a regular List, instead. I think that is why this error message is happening, but I'm not sure why loading a new, transient object would result in a different list type for the categories. Perhaps it is because marshmallow-sqlalchemy is anticipating that these are new categories that I would want to persist? But I haven't found anything in the documentation supporting that theory.
I've attempted to modify the ProductSchema as well, and change the categories to categories = ma.Nested(CategorySchema, many=True), and I've also tried categories = fields.Related(CategorySchema), to no avail. Any help would be greatly appreciated!
This is a lot to chew on, so I thought I'd give a simpler explanation since I've had time to think through this. It seems like editing an item with a one-to-many relation persists all relations as expected.
updated_item = schema.load(request_data, session=db.session, instance=existing_item)
persist this works. But when I'm trying to create a new record, i.e...
new_item = schema.load(request_data, session=db.session, partial=True)
I get this error about an _sa_adapter. Is there any details I may be missing on persisting one-to-many relationships when creating a new item from a schema?
@zeke8402 I have been using this pattern for quite some time and havent found any issues. Which version of the library are you using ? Do you have a categories relationship in the Product sqlalchemy model ? Could you show us your sqla models ? What is the request_data you are using ?
Note - i dont use partial=True, ib my case we create it from scratch
Perhaps it does relate, as I have a pivot table for the many-to-many relation
product_product_categories = db.Table(
'product_product_categories',
db.Column(
'product_id',
db.Integer,
db.ForeignKey(
'product_products.id',
ondelete='CASCADE'
),
primary_key=True,
nullable=False,
index=True
),
db.Column(
'category_id',
db.Integer,
db.ForeignKey(
'product_categories.id',
ondelete='CASCADE'
),
primary_key=True,
nullable=False,
index=True
)
)
Again marshmallow-sqlalchemy has no issues updating this relationship, it's only when creating a new product does this happen.