pythonflasksqlalchemyflask-sqlalchemyflask-marshmallow

"Unknown field." in a flask app, when the field exists


I spent all afternoon trying to figure this out. I've checked the flask documentation, mostly flask-marshmallow documentation most notably the sqlalchemy integration part and some other stackoverflow questions.

Is this something to do with serialization? I thought it was taken care of by using the flask-sqlalchemy package?

When I run this with a postman request, I get:

{
  "name": [
    "Unknown field."
  ]
}

My code:

Schema

from ma import ma
from models.form import FormModel

class FormSchema(ma.SQLAlchemySchema):
    class Meta:
        model = FormModel

Model

from db import db

class FormModel(db.Model):
    __tablename__ = "forms"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))

Resource

from flask_restful import Resource
from flask import request
from models.form import FormModel
from schemas.form import FormSchema
from db import db

form_schema = FormSchema()

class NewForm(Resource):
    @classmethod
    def post(cls):
        print("Request:")
        print(request.get_json())
        print("Form schema load:")
        #print(form_schema.load(request.get_json()))
        form = form_schema.load(request.get_json())
        print("Form")
        #print(form)

        db.session.add(form)
        db.session.commit()
        #form_schema.dump(form)

app.py

from flask import Flask, jsonify
from flask_restful import Api
from marshmallow import ValidationError

from db import db
from ma import ma

from models.form import FormModel
from schemas.form import FormSchema
from resources.form import NewForm

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///test.db"
api = Api(app)


@app.before_first_request
def create_tables():
    db.create_all()

@app.errorhandler(ValidationError)
def handle_marshmallow_validation(err):
    return jsonify(err.messages), 400

api.add_resource(NewForm, "/form")

if __name__ == "__main__":
    db.init_app(app)
    ma.init_app(app)
    app.run(port=5000, debug=True)

db.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

ma.py

from flask_marshmallow import Marshmallow

ma = Marshmallow()

Solution

  • Figured it out!

    The schema isn't correct. It should be:

    class FormSchema(ma.SQLAlchemyAutoSchema):
        class Meta:
            model = FormModel
            load_instance = True
    

    I changed ma.SQLAlchemySchema to ma.SQLAlchemyAutoSchema

    And added load_instance = True