Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'list' object has no attribute '_sa_adapter' #346

Open
zeke8402 opened this issue Sep 21, 2020 · 3 comments
Open

'list' object has no attribute '_sa_adapter' #346

zeke8402 opened this issue Sep 21, 2020 · 3 comments

Comments

@zeke8402
Copy link

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!

@zeke8402
Copy link
Author

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?

@AbdealiLoKo
Copy link
Collaborator

@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

@zeke8402
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants