Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLAlchemy @property causes 'Unknown Field' error in Marshmallow with dump_only

I'm using flask-marshmallow (marshmallow=v3.0.0rc1, flask-marshmallow=0.9.0) and flask-sqlalchemy (sqlalchemy=1.2.16, flask-sqlalchemy=2.3.2)

I have this model and schema.

from marshmallow import post_load, fields
from .datastore import sqla_database as db
from .extensions import marshmallow as ma

class Study(db.Model):
    _id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)

    tests = db.relationship("Test", backref="study", lazy='select', cascade="all, delete-orphan")

    @property
    def test_count(self):
        return len(self.tests)

class StudySchema(ma.ModelSchema):
    test_count = fields.Integer(dump_only=True)
    class Meta:
        model = Study
        sqla_session = db.session

schema = StudySchema()
payload = request.get_json()
schema.load(data=payload, instance=Study.query.get(payload["_id"]))
schema.session.commit()

If I perform a PUT operation with this payload {'_id': 1, 'name': 'Study1', 'test_count': 0} I get the following exception marshmallow.exceptions.ValidationError: {'test_count': ['Unknown field.']}

If I remove the dump_only=True I get this exception AttributeError: can't set attribute which makes sense to me because it's trying to set test_count with no setter method on model class.

What I do not understand is why is the attribute is not ignored with dump_only. Why is marshmallow still trying to validate and understand this field during load when it's marked as dump_only?

like image 871
Josh Avatar asked Jan 27 '19 18:01

Josh


1 Answers

In marshmallow 2, unknown or dump_only fields are ignored from input. Unless the user decides to add his own validation to error on them.

In marshmallow 3, we changed that to offer three possibilities (see docs):

  • RAISE (default)
  • EXCLUDE (like marshmallow 2)
  • INCLUDE (pass data without validation)

There's been discussions about how to deal with dump_only fields and we came to the conclusion that from client perspective, those should be treated just as unknown fields (see https://github.com/marshmallow-code/marshmallow/issues/875).

Bottom line, your PUT payload should not include dump_only fields. Or you could set the EXCLUDE policy to your schema, but I'd favor the former option.

like image 177
Jérôme Avatar answered Oct 26 '22 23:10

Jérôme