You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A DateTime field to track updated_at timestamp on the model
A marshmallow-based custom de/serialization (and the corresponding marshmallow_enum) to correctly deserialize enums
problem
PATCH requests to update enum fields fail because the resources.py:patch() relies on directly setting the attributes of the sqlalchemy model instance to whatever values are provided by the request data dictionary (which are usually string/unicode representations of model field values since the 'data' object comes in as JSON). Normally, upon session.commit(), SQLAlchemy would convert the literal values to the proper representations of the model fields (in this case, to something like <EnumClass.TYPE_A: 0> instead of to 'TYPE_A', its literal representation). However, the patch method has to flush() the changes first in order to allow post-processors to make any changes. Unfortunately, the serializer is called before the sqlalchemy commit(), and the custom serializer fails because it expected an actual Enum but instead received a string representation of the field.
Stacktrace of the failing unit test:
self = <fields.EnumField(default=<marshmallow.missing>, attribute=None, validate=None...'type': u'Invalid input type.', 'must_be_string': 'Enum name must be string'})> value = 'HOME', attr = 'address_type', obj = <tests.test_updating.Address object at 0x1099f9c90> AttributeError: 'unicode' object has no attribute 'name' venv/lib/python2.7/site-packages/marshmallow_enum/__init__.py:74: AttributeError
Updated to first deserialize the partial document (request data passed to patch()) in order to force the conversion of the input enum value into its Enum representation so that setattr() in resources.py:_update_instance() sets the correct representation. This approach seems to solve the issue, but it causes most tests in test_updating.py to fail because the DefaultDeserializer's allow_client_generated_ids flag isn't set, and I cannot find a way to set it to True to avoid the ClientGeneratedIDNotAllowed
…rialization issue#679
- add dependencies for enum, marshmallow_enum serialization
- create marshmallow-based custom de/serialization to demonstrate
the issue
- add models, schema, serializers and a test case for updating enum fields. the test case fails as expected
- todo: apply a fix to the issue
kiptoomm
pushed a commit
to kiptoomm/flask-restless
that referenced
this issue
Feb 2, 2018
…tance
- the idea is to deserialize the input fields into their actual
representations so that the setattr method of _update_instance() sets the real instance values and that custom serialization of enum fields works as expected
- this approach causes most unit tests in test_updating.py to fail :( due to the GeneratedIDNotAllowed exception. workaround?
- jfinkels#679
setup
An SQLalchemy model that has
problem
PATCH requests to update enum fields fail because the
resources.py:patch()
relies on directly setting the attributes of the sqlalchemy model instance to whatever values are provided by the request data dictionary (which are usually string/unicode representations of model field values since the 'data' object comes in as JSON). Normally, upon session.commit(), SQLAlchemy would convert the literal values to the proper representations of the model fields (in this case, to something like<EnumClass.TYPE_A: 0>
instead of to 'TYPE_A', its literal representation). However, the patch method has to flush() the changes first in order to allow post-processors to make any changes. Unfortunately, the serializer is called before the sqlalchemy commit(), and the custom serializer fails because it expected an actual Enum but instead received a string representation of the field.Stacktrace of the failing unit test:
self = <fields.EnumField(default=<marshmallow.missing>, attribute=None, validate=None...'type': u'Invalid input type.', 'must_be_string': 'Enum name must be string'})> value = 'HOME', attr = 'address_type', obj = <tests.test_updating.Address object at 0x1099f9c90> AttributeError: 'unicode' object has no attribute 'name' venv/lib/python2.7/site-packages/marshmallow_enum/__init__.py:74: AttributeError
A more detailed background on the problem is discussed on this issue
justanr/marshmallow_enum#19
and demonstrated by this sample project:
https://github.com/kiptoomm/flask_and_restless
attempted fix
Updated to first deserialize the partial document (request data passed to
patch()
) in order to force the conversion of the input enum value into its Enum representation so thatsetattr()
inresources.py:_update_instance()
sets the correct representation. This approach seems to solve the issue, but it causes most tests in test_updating.py to fail because the DefaultDeserializer's allow_client_generated_ids flag isn't set, and I cannot find a way to set it to True to avoid theClientGeneratedIDNotAllowed
Please see commit
af963701ee020f71ab2fe51331a35aac1c7e2d85
in the debug_issue_679 branch of my fork: https://github.com:kiptoomm/flask-restlessAny ideas on how to fix the exception, or advice on a cleaner approach?
The text was updated successfully, but these errors were encountered: