flask-marshmallow
flask-marshmallow copied to clipboard
'DummySession' object has no attribute 'query'
We have been using flask-marshmallow 0.6.0 with marshmallow-sqlalchemy 0.3.0 for some time now, and been quite happy. However, in trying to upgrade our packages we have encountered the error message above.
It appears that marshmallow-sqlalchemy is now trying to actually manage adding/merging the models with the session. Personally, I don't want that. I want marshmallow to handle the deserialization and leave it to me to decide when and how I want to add or merge the model with the session, as we have been doing for some time. I have suggested on their issue board where others had brought up the issue that it would be nice if their code just skipped the session management parts if the session was none (see https://github.com/marshmallow-code/marshmallow-sqlalchemy/issues/62). If they did that, then you wouldn't need to have a DummySession class at all. I do not know how amenable they will be to that suggestion.
The alternative is unfortunately to have to make DummySession implement methods to avoid generating errors, but this requires not just the query method but then it would appear filter_by, one, and first.
Or perhaps there is an alternative workaround that you already have in place. If so, I would be anxious to hear it.
Thanks.
Oh the full traceback is
Traceback (most recent call last): File "tests.py", line 245, in runTest (obj, errors) = schema.loads(example_str[name]) File "/home/davism/Src/atsdb/venv/lib/python2.7/site-packages/marshmallow/schema.py", line 564, in loads return self.load(data, many=many, partial=partial) File "/home/davism/Src/atsdb/venv/lib/python2.7/site-packages/marshmallow_sqlalchemy/schema.py", line 186, in load return super(ModelSchema, self).load(data, _args, *_kwargs) File "/home/davism/Src/atsdb/venv/lib/python2.7/site-packages/marshmallow/schema.py", line 542, in load result, errors = self._do_load(data, many, partial=partial, postprocess=True) File "/home/davism/Src/atsdb/venv/lib/python2.7/site-packages/marshmallow/schema.py", line 646, in _do_load result = self._invoke_load_processors(POST_LOAD, result, many, original_data=data) File "/home/davism/Src/atsdb/venv/lib/python2.7/site-packages/marshmallow/schema.py", line 767, in _invoke_load_processors data=data, many=many, original_data=original_data) File "/home/davism/Src/atsdb/venv/lib/python2.7/site-packages/marshmallow/schema.py", line 865, in _invoke_processors data = utils.if_none(processor(data), data) File "/home/davism/Src/atsdb/venv/lib/python2.7/site-packages/marshmallow_sqlalchemy/schema.py", line 169, in make_instance instance = self.instance or self.get_instance(data) File "/home/davism/Src/atsdb/venv/lib/python2.7/site-packages/marshmallow_sqlalchemy/schema.py", line 154, in get_instance return self.session.query( AttributeError: 'DummySession' object has no attribute 'query'
Hi @medavis, did you happen to solve this problem? I encountered it myself today and I have not found a suitable solution (yet).
I am afraid I have not. We have just not upgraded yet, and pressed ahead.
I do wonder however if the cause of my problem had to do with a configuration problem. We have found that the DummySession object is there even in the older code, and the error can be generated even with the older code if one accidentally ends up calling the marshmallow code before the application and session have been configured. So, my best suggestion is to double check for that first.
Malcolm
From: Andreas [mailto:[email protected]] Sent: Tuesday, September 27, 2016 7:27 PM To: marshmallow-code/flask-marshmallow [email protected] Cc: Davis, Malcolm [email protected]; Mention [email protected] Subject: Re: [marshmallow-code/flask-marshmallow] 'DummySession' object has no attribute 'query' (#44)
Hi @medavishttps://github.com/medavis, did you happen to solve this problem? I encountered it myself today and I have not found a suitable solution (yet).
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/marshmallow-code/flask-marshmallow/issues/44#issuecomment-250028467, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ANpDiXUo1gJvzW15ogxSNQf5Ft1fcCr9ks5quaY6gaJpZM4Il-H6.
This message (including any attachments) may contain confidential, proprietary, privileged and/or private information. The information is intended to be for the use of the individual or entity designated above. If you are not the intended recipient of this message, please notify the sender immediately, and delete the message and any attachments. Any disclosure, reproduction, distribution or other use of this message or any attachments by an individual or entity other than the intended recipient is prohibited.
I have now found a workaround, which is to pass a database session explicitly to the load method like this:
my_schema.load(request.json, session=db.session)
Where db.session comes from flask_sqlalchemy. EDIT: but that does not seem to be what you tried to do.
Thanks
Sent from my phone. On Sep 28, 2016 6:12 AM, Andreas [email protected] wrote:
I have now found a workaround, which is to pass a database session explicitly to the load method like this:
my_schema.load(request.json, session=db.session)
Where db.session comes from flask_sqlalchemy. Hope this helps.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/marshmallow-code/flask-marshmallow/issues/44#issuecomment-250127062, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ANpDiU41-sPVq_NC4icmFJp3YnOpOsOBks5quj2JgaJpZM4Il-H6.
This message (including any attachments) may contain confidential, proprietary, privileged and/or private information. The information is intended to be for the use of the individual or entity designated above. If you are not the intended recipient of this message, please notify the sender immediately, and delete the message and any attachments. Any disclosure, reproduction, distribution or other use of this message or any attachments by an individual or entity other than the intended recipient is prohibited.
@AndreasGB, have you by any chance found a way to deal with nested schemas? Your method works when not using nested schema, but the session is not passed from one Schema to the other, therefore we still end up with a DummySession for the Nested Schema. And it yields the same 'DummySession' object has no attribute 'query'
Or, did anyone found a way to deal with foreign keys on SQLAlchemy models and avoid this issue with Marshmallow? (perhaps I'm just doing it the wrong way..?)
Thank you
Answer to my own question is here: https://github.com/marshmallow-code/marshmallow-sqlalchemy/issues/20#issuecomment-136400602
The session simply has to be set when declaring the schemas.
I have now found a workaround, which is to pass a database session explicitly to the load method like this:
my_schema.load(request.json, session=db.session)Where db.session comes from flask_sqlalchemy. EDIT: but that does not seem to be what you tried to do.
I had the same issue, and this does work. Thanks
I'm having the same issue ( AttributeError: 'DummySession' object has no attribute 'query' ), but only when i run tests using pytest with sqlite db. When i use mariadb, and curl, POST works properly. Any idea on what's going on?
Correction, it appears that the problem manifests itself only when i run unit tests (pytest, flask test_client)
I'm having the same issue ( AttributeError: 'DummySession' object has no attribute 'query' ), but only when i run tests using
pytestwith sqlite db. When i use mariadb, and curl, POST works properly. Any idea on what's going on?Correction, it appears that the problem manifests itself only when i run unit tests (pytest, flask test_client)
Same for me.
I am running into this problem as well with pytest, flask_test_client and nested Schema's (not with simple fields).
There seems to be no problem at all when running the code in development or production, only in testing does this error show up.
I know this is incredibly late to the game, but just in case someone else is searching, as I had been for some considerable time:
If you are using marshmallow_sqlalchemy in addition to flask_marshmallow (if you're using flask_sqlalchemy then you probably are), then flask_marshmallow's usage of Nested is not going to work in unit testing. You must use the marshmallow_sqlalchemy.fields.Nested in conjunction with an override on session during your load in order to get this to work. Either interpretation will work for a production run, which is why it seems a little tough to track down.
See https://github.com/marshmallow-code/marshmallow-sqlalchemy/issues/298 for more info.
I have now found a workaround, which is to pass a database session explicitly to the load method like this:
my_schema.load(request.json, session=db.session)Where db.session comes from flask_sqlalchemy. EDIT: but that does not seem to be what you tried to do.
This workaround has worked for me too.
There is another workaround that doesn't require passing session as a kwarg into every call to load/dump, and has the added benefit of also working out of the box with flask-smorest:
# app/schemas.py
from app.extensions import db # the Flask-SQLAlchemy extension instance
from app.extensions import ma as flask_ma # the Flask-Marshmallow extension instance
# this pattern also works with flask_ma.SQLAlchemyAutoSchema
class SQLAlchemySchema(flask_ma.SQLAlchemySchema):
class Meta(flask_ma.SQLAlchemySchema.Meta):
sqla_session = db.session
# all of your model schemas should inherit from your schema base class
class YourSchema(SQLAlchemySchema):
class Meta(SQLAlchemySchema.Meta): # <- note Meta must *also* subclass the base class's Meta
model = YourModel
# ... field definitions
Upstream devs: The cause of the original bug has to do with the fact that marshmallow.schema.SchemaMeta calls klass.OPTIONS_CLASS(meta, ordered=ordered) before the Flask-Marshmallow extension instance has a chance to set the correct session object on OPTIONS_CLASS. (The instantiation happens in type.__new__, and thus at import-time, so by the time init_app is called by user code, it's too late.) There is probably possibly a way to use the descriptor protocol to make this work correctly, but I didn't dive into it any deeper.
I am working on a new project and was hoping that all of this was cleared up. But once again I am encountering the dreaded "AttributeError: 'DummySession' object has no attribute 'get'" error. The error arises as soon as one of my nested, many=true, lists contains what should be a preexisting object. I have tried getting the correct session into the schema object in a variety of ways, but I can still see in the debugger that the nested schema's session attribute points to a DummySession object.
Things I have tried:
- My load calls all specify
parent_schema.load(input_json, session=db.session) - I have set the
sessionattribute of the schema's innerMetaclass todb.sessionin the class definition, and I can see thatself.Meta.sessionis set correctly at the point the DummySession error is raised - I have set the
sessionattribute of the schema itself to mydb.sessionvalue in the schema definition, but it is getting overwritten with the DummySession by the time the error occurs - I have added
session=db.sessionto my instantiation of theparent_schemainstance, hoping that that kwarg might get passed down to the instantiation of the nested schema, but that appears to have had no effect
Some other things to note. I do have load_instance=True set for each of the schemas, parent and nested fields. Also, I am using the latest version of all of the Flask, Marshmallow, and SQLAlchemy packages.
What do I need to do to get the nested Schema to use the right session?
(Just as an inconsequential note, I am the medavis who started this issue back in 2016.)
Ah. I have found the combination that works. If I set the Meta.sqla_session attribute to my db.session in the class definition, the DummySession errors go away.