marshmallow-sqlalchemy
marshmallow-sqlalchemy copied to clipboard
Support for Dictionary Collections (collection=attribute_keyed_dict)
In sqlalchemy I can map a collection as a dictionary rather than a list: https://docs.sqlalchemy.org/en/20/orm/collection_api.html#dictionary-collections
Is this supported at all by marshmallow-sqlalchemy?
You can deserialize to nested dictionaries for relationships by passing columns to auto_field
from pprint import pprint
import sqlalchemy as sa
from sqlalchemy.orm import DeclarativeBase, relationship, sessionmaker
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema, auto_field
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "user"
id = sa.Column(sa.Integer, primary_key=True)
full_name = sa.Column(sa.String(255))
blog_posts = relationship(lambda: BlogPost, back_populates="author")
class BlogPost(Base):
__tablename__ = "blog_post"
id = sa.Column(sa.Integer, primary_key=True)
title = sa.Column(sa.String(255), nullable=False)
author_id = sa.Column(sa.Integer, sa.ForeignKey(User.id), nullable=False)
author = relationship(User)
class AuthorSchema(SQLAlchemyAutoSchema):
class Meta:
model = User
include_relationships = True
blog_posts = auto_field(columns=("id", "title"))
engine = sa.create_engine("sqlite:///:memory:")
Session = sessionmaker(engine)
Base.metadata.create_all(engine)
with Session() as session:
user = User(full_name="Freddie Mercury")
post = BlogPost(title="Bohemian Rhapsody Revisited", author=user)
session.add_all([user, post])
session.commit()
assert len(user.blog_posts) == 1
session.refresh(user)
dumped_user = AuthorSchema().dump(user)
pprint(dumped_user, indent=2)
# { 'blog_posts': [{'id': 1, 'title': 'Bohemian Rhapsody Revisited'}],
# 'full_name': 'Freddie Mercury',
# 'id': 1}
However, if User.blog_posts model is changed to use, attribute_keyed_dict, the serialized input is broken
class User(Base):
__tablename__ = "user"
id = sa.Column(sa.Integer, primary_key=True)
full_name = sa.Column(sa.String(255))
blog_posts = relationship(
lambda: BlogPost,
back_populates="author",
collection_class=attribute_keyed_dict("id"),
)
dumped_user = AuthorSchema().dump(user)
pprint(dumped_user, indent=2)
# { 'blog_posts': [{'id': 1, 'title': 'Bohemian Rhapsody Revisited'}],
# 'full_name': 'Freddie Mercury',
# 'id': 1}
i'll leave this issue open as a feature request to support attribute_keyed_dict