question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Nessted schema: Inherit session from parent.

See original GitHub issue

Deserialization of nested objects raises: ValueError: Deserialization requires a session. Example below:

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, backref
from marshmallow import fields
from marshmallow_sqlalchemy import field_for, ModelSchema


class Student(Model):
    __tablename__ = "students"

    id = Column(Integer, primary_key=True)
    age = Column(Integer)
    name = Column(String, nullable=False)

class Account(Model):
    __tablename__ = "accounts"

    id = Column(Integer, primary_key=True)
    balance = Column(Integer, default=0)

    student_id = Column(Integer, ForeignKey("students.id"))
    student = relationship("Student", backref="accounts")

class AccountSchema(ModelSchema):
    class Meta:
        model = Account


class StudentSchema(ModelSchema):
    class Meta:
        model = Student

    accounts = fields.Nested(
        AccountSchema, only=("id", "balance"), many=True
    )

data = {
    "name": "Python", "age": 17,
    "accounts": [{"balance": 100}, {"balance": 150}] 
}
obj, errors = StudentSchema(session=self.db.session).load(data)


The problem can be solve by passing session from parent schema inside the property ‘schema’ of class ‘Nested’ (file: fields.py, lines: 405-420). Or maybe there is any other solution?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

8reactions
torypagescommented, Sep 10, 2017

I think a complication is that this is sort of marshmallow_sqlalchemy’s problem. But I think I have a hack for the time being.

The key section is:

    @pre_load
    def set_field_session(self, data):
        self.fields['children'].schema.session = self.session

Here is the entire proof of concept:

from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import orm
from marshmallow import (
    fields as m_fields,
    pre_load,
)
from marshmallow_sqlalchemy import (
    ModelSchema,
)

e = create_engine("sqlite:///")
session = orm.scoped_session(orm.sessionmaker())
session.configure(bind=e)

Base = declarative_base()

association_table = Table('association', Base.metadata,
    Column('left_id', Integer, ForeignKey('left.id')),
    Column('right_id', Integer, ForeignKey('right.id'))
)

class Parent(Base):
    __tablename__ = 'left'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    children = relationship(
        "Child",
        secondary=association_table,
        back_populates="parents")

class Child(Base):
    __tablename__ = 'right'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    parents = relationship(
        "Parent",
        secondary=association_table,
        back_populates="children")

class ChildSchema(ModelSchema):
    class Meta:
        model = Child

class ParentSchema(ModelSchema):
    children = m_fields.Nested(ChildSchema, many=True)

    class Meta:
        model = Parent

    @pre_load
    def set_field_session(self, data):
        self.fields['children'].schema.session = self.session

cj = {
    'name': 'tiny_tim'
}

j = {
    'name': 'bob',
    'children': [cj]
}
x = ParentSchema().load(j, session=session).data
print(x.children[0].name)
print(x.name)

And this is the output:

tiny_tim
bob

I haven’t used this hack extensively yet, but, I just got past the ValueError: Deserialization requires a session error and I’m pretty excited!

0reactions
multimericcommented, Aug 8, 2019

While this particular issue is a marshmallow-sqlalchemy issue, I can see some need for a generalized mechanism for Marshmallow schemas to pass metadata down to nested schemas. This would solve this problem for marshmallow-sqlalchemy, and other downstream libraries too.

Broadly we need some way for schema arguments to continuously pass data down to nested schemas, without any of them ever breaking the chain. The arguments we pass down should obviously not include the normal schema constructor arguments like many, exclude, include etc, but they should include everything else. So either we take the remaining **kwargs and propagate them down, or we have a new, separate argument called recursive_args or something.

In either of those cases, it should be as simple as storing the metadata args, and using them whenever we construct a nested schema. e.g.

class BaseSchema(base.SchemaABC):
    def __init__(self, extra=None, only=None, exclude=(), prefix='', strict=None,
                 many=False, context=None, load_only=(), dump_only=(),
                 partial=False, **kwargs):
        self.recursive_args = kwargs


class Nested(Field):
    @property
    def schema(self):
        self.__schema = self.nested(many=self.many,
                only=only, exclude=self.exclude, context=context,
                load_only=self._nested_normalized_option('load_only'),
                dump_only=self._nested_normalized_option('dump_only'), **recursive_args)

That said, I’m not sure if it’s possible for a Nested field to access properties on the parent Schema (recursive_args), but perhaps there should be a mechanism for this too.

Thoughts?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Mongoose schema - nested objects with shared properties
I am creating objects that "extend" other objects. For example, I have a person object that I want to use as the starting...
Read more >
Analyze complex data types in Azure Synapse Analytics
Analyzing nested schema and arrays can involve time-consuming and complex SQL queries. Additionally, it can be difficult to rename or cast ...
Read more >
Specify nested and repeated columns in table schemas
This page describes how to define a table schema with nested and repeated columns in BigQuery. For an overview of table schemas, see...
Read more >
Nesting Schemas — marshmallow 3.19.0 documentation
Schemas can be nested to represent relationships between objects (e.g. foreign key relationships). For example, a Blog may have an author represented by...
Read more >
Mapping Class Inheritance Hierarchies
In joined table inheritance, each class along a hierarchy of classes is represented by a distinct table. Querying for a particular subclass in ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found