Hello all, I am attempting to understand how marshmallow works. I am getting the above error
with the below code, and the below dataset
{'name': 'kay',
'id': 1
'children': [
{'name': 'Taylor', 'id': 1,
'toys': [
{'name': 'video game','id': 1 }
]
},
{'name': 'Paige', 'id': 2,
'toys': [
{'name': 'baby', 'id': 1}
]
}],
}
the schemas are auto-generated by a superclass named BaseModel via classmethods and __init_subclass__, but look something like this:
class GeneratedSchema(Schema):
class Meta:
fields=[# auto generated from column keys if none, else from the class attribute "fields"]
model= the class that BaseModel recieved
strict=True
# the nested field is only included if a relationship is detected
"field_name"= fields.Nested(theNestedSchema,
many= True if the Column's uselist=None or False
# this definition continues for all columns
"other_fields" = the marshmallow field associated with the column's inner data type
Notes about the SQLAlchemy models,
The schema attribute grabs default and required attributes off the Column() Instance
if Column.nullable== false or Column.nullable is None, then required=True. Else required=False
if Column.default != None, then the value is taken from Column.default
if Column.uselist == None or True, then fields.Nested.many==True else fields.Nested.many==False
the schema is placed on each class under the name 'schema'
And the SQLAlchemy Models
class Toy(BaseModel):
fields=['id','name']
id=db.Column(db.Integer(), primary_key=True)
child_id = db.Column(db.Integer, db.ForeignKey('child.id'))
name = db.Column(db.String)
class Child(BaseModel):
fields= ['id','name','toys']
id=db.Column(db.Integer(), primary_key=True)
parent_id= db.Column(db.Integer, db.ForeignKey('parent.id'))
name = db.Column(db.String)
toys = db.relationship('Toy')
class Parent(BaseModel):
id=db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String)
children = db.relationship('Child')
db.create_all()
if __name__ == "__main__":
parent =
Parent(id=1,name='kay',
child=Child(name='jordan'),
children=[
Child(id=1,name='Taylor',
toys=[
Toy(id=1,name='video game')
]),
Child(id=2,name='Paige',
toys=[
Toy(id=1,name='baby')
])
]
)
db.session.add(parent)
db.session.commit()
print( parent.schema.dump(parent))
Can anyone spot where my problem is?
I have also noticed that an Integer value of 0 for an Integer field shows as None when dumped with schema.dump.
Are you using marshmallow-sqlalchemy?
I am using flask-marshmallow, which in turn uses marshmallow-sqlalchemy
ive attached some more data, hopefully it will help
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
db = SQLAlchemy(app)
ma = Marshmallow(app)
class Toy(db.Model):
fields = ['id', 'name']
id = db.Column(db.Integer(), primary_key=True)
child_id = db.Column(db.Integer, db.ForeignKey('child.id'))
name = db.Column(db.String)
class Child(db.Model):
fields = ['id', 'name', 'toys']
id = db.Column(db.Integer(), primary_key=True)
parent_id = db.Column(db.Integer, db.ForeignKey('parent.id'))
name = db.Column(db.String)
toys = db.relationship('Toy')
class Parent(db.Model):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String)
children = db.relationship('Child')
class ToySchema(ma.ModelSchema):
class Meta:
model = Toy
class ChildSchema(ma.ModelSchema):
class Meta:
model = Child
class ParentSchema(ma.ModelSchema):
class Meta:
model = Parent
db.create_all()
if __name__ == '__main__':
parent = Parent(
name='kay',
children=[
Child(
name='Taylor',
toys=[Toy(name='video game')],
),
Child(
name='Paige',
toys=[Toy(name='baby')],
),
],
)
db.session.add(parent)
db.session.commit()
print(ParentSchema().dump(parent))
This example is working for me, so you might focus on debugging your BaseModel implementation.
Does that include nested fields in the schemas ? I’m defining nested fields on the schemas when a Relationship column is on the model class. The error only happens on load, not dump. Does that example validate data in nested columns?
Sent from my iPhone
On Mar 8, 2019, at 8:33 AM, Jared Deckard notifications@github.com wrote:
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallowapp = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'db = SQLAlchemy(app)
ma = Marshmallow(app)class Toy(db.Model):
fields = ['id', 'name']
id = db.Column(db.Integer(), primary_key=True)
child_id = db.Column(db.Integer, db.ForeignKey('child.id'))
name = db.Column(db.String)class Child(db.Model):
fields = ['id', 'name', 'toys']
id = db.Column(db.Integer(), primary_key=True)
parent_id = db.Column(db.Integer, db.ForeignKey('parent.id'))
name = db.Column(db.String)
toys = db.relationship('Toy')class Parent(db.Model):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String)
children = db.relationship('Child')class ToySchema(ma.ModelSchema):
class Meta:
model = Toyclass ChildSchema(ma.ModelSchema):
class Meta:
model = Childclass ParentSchema(ma.ModelSchema):
class Meta:
model = Parentdb.create_all()
if __name__ == '__main__':
parent = Parent(
name='kay',
children=[
Child(
name='Taylor',
toys=[Toy(name='video game')],
),
Child(
name='Paige',
toys=[Toy(name='baby')],
),
],
)
db.session.add(parent)
db.session.commit()
print(ParentSchema().dump(parent))
This example is working for me, so you might focus on debugging your BaseModel implementation.—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.
The docs for marshmallow-sqlalchemy show how to overload relationships with nested fields.
https://marshmallow-sqlalchemy.readthedocs.io/en/latest/recipes.html#overriding-generated-fields
class ChildSchema(ma.ModelSchema):
toys = ma.Nested(ToySchema, many=True)
class Meta:
model = Child
class ParentSchema(ma.ModelSchema):
children = ma.Nested(ChildSchema, many=True)
class Meta:
model = Parent
db.create_all()
if __name__ == '__main__':
schema = ParentSchema()
data = {'name': 'kay',
'id': 1,
'children': [
{'name': 'Taylor', 'id': 1,
'toys': [
{'name': 'video game','id': 1 }
]
},
{'name': 'Paige', 'id': 2,
'toys': [
{'name': 'baby', 'id': 1}
]
}],
}
print(schema.load(data).data)
# <Parent (transient 4583120144)>
Most helpful comment
The docs for marshmallow-sqlalchemy show how to overload relationships with nested fields.
https://marshmallow-sqlalchemy.readthedocs.io/en/latest/recipes.html#overriding-generated-fields