Je travaille sur une API REST JSON REST de base utilisant Flask-Restless, Flask-SQLAlchemy et Marshmallow.Flask-Restless & Marshmallow: l'objet 'dict' n'a pas d'attribut '_sa_instance_state'
Je rencontre un problème lors de l'utilisation de cette combinaison de bibliothèques, mais uniquement lorsque j'active la désérialisation à l'aide de Marshmallow.
J'ai largement recherché l'erreur, mais je ne trouve que des problèmes similaires lors de l'utilisation de relations de base de données, ce que je ne suis pas.
J'ai supprimé autant de code que possible de mon application tout en obtenant toujours la même erreur. Les blocs de code suivants sont 1: 1 ce qui s'exécute localement.
models.py:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Case(db.Model):
__tablename__ = 'case'
id = db.Column(db.Integer, primary_key=True)
amount = db.Column(db.Integer, nullable=False)
serializers.py:
from marshmallow import Schema
class CaseSchema(Schema):
pass # for simplicity - nothing works
case_schema = CaseSchema()
def case_serializer(instance):
return case_schema.dump(instance).data
def case_deserializer(data):
return case_schema.load(data).data
main.py:
from flask import Flask
import flask_restless
import models
import serializers
app = Flask(__name__)
app.config['DEBUG'] = True
models.db.init_app(app)
def init_db():
with app.app_context():
models.db.create_all()
def init_api():
init_db()
with app.app_context():
api_manager = flask_restless.APIManager(app, flask_sqlalchemy_db=models.db)
api_manager.create_api(models.Case, methods=['GET', 'POST', 'PUT'],
serializer=serializers.case_serializer,
deserializer=serializers.case_deserializer) # <- stuff breaks when enabling this line
if __name__ == "__main__":
init_db()
init_api()
app.run()
tests.py:
import json
import os
import myapp
import unittest
import tempfile
with myapp.app.app_context():
myapp.init_api()
class MyappTestCase(unittest.TestCase):
def setUp(self):
self.db_fd, myapp.app.config['DATABASE'] = tempfile.mkstemp()
myapp.app.config['TESTING'] = True
self.app = myapp.app.test_client()
def tearDown(self):
os.close(self.db_fd)
os.unlink(myapp.app.config['DATABASE'])
def test_create_case(self):
msg = {
"amount": 1038,
}
post_response = self.app.post("/api/case", data=json.dumps(msg),
content_type="application/json")
assert post_response.status_code == 201
if __name__ == '__main__':
unittest.main()
Versions utilisées:
Flask==0.11
Flask-SQLAlchemy==2.1
Flask-Restless==0.17.0
mysqlclient==1.3.7
SQLAlchemy-Utils==0.32.8
marshmallow==2.9.0
Enfin, la pleine STACKTRACE lorsque les tests en cours d'exécution:
======================================================================
ERROR: test_create_case (__main__.myappTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/sqlalchemy/orm/session.py", line 1584, in add
state = attributes.instance_state(instance)
AttributeError: 'dict' object has no attribute '_sa_instance_state'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "myapp_tests.py", line 37, in test_create_case
content_type="application/json")
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/werkzeug/test.py", line 788, in post
return self.open(*args, **kw)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/testing.py", line 113, in open
follow_redirects=follow_redirects)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/werkzeug/test.py", line 751, in open
response = self.run_wsgi_app(environ, buffered=buffered)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/werkzeug/test.py", line 668, in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/werkzeug/test.py", line 871, in run_wsgi_app
app_rv = app(environ, start_response)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/app.py", line 2000, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/app.py", line 1991, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/app.py", line 1567, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/app.py", line 1641, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/app.py", line 1544, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/app.py", line 1639, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/app.py", line 1625, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask_restless/views.py", line 157, in decorator
return func(*args, **kw)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/mimerender.py", line 244, in wrapper
result = target(*args, **kwargs)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/views.py", line 84, in view
return self.dispatch_request(*args, **kwargs)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask/views.py", line 149, in dispatch_request
return meth(*args, **kwargs)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask_restless/views.py", line 189, in wrapped
return func(*args, **kw)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/flask_restless/views.py", line 1449, in post
self.session.add(instance)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/sqlalchemy/orm/scoping.py", line 157, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/Users/myuser/.virtualenvs/myenv/lib/python3.5/site-packages/sqlalchemy/orm/session.py", line 1586, in add
raise exc.UnmappedInstanceError(instance)
sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.dict' is not mapped