Source code for backend.api.wrapped_serializer

from marshmallow import pre_load, post_dump

from backend.utils import pluralize

from .model_serializer import ModelSerializer


[docs]class WrappedSerializer(ModelSerializer): """ Extends :class:`backend.api.ModelSchema` to automatically wrap serialized results with the model name, and automatically unwrap it when loading. NOTE: this might not behave as you'd expect if your serializer uses nested fields (if a nested object's serializer is also a WrappedSerializer, then the nested objects will also end up wrapped, which probably isn't what you want...) Example usage:: class Foo(PrimaryKeyMixin, BaseModel): name = Column(String) class FooSerializer(WrappedSerializer): class Meta: model = Foo foo_serializer = FooSerializer() foo = Foo(id=1, name='FooBar') foo_json = foo_serializer.dump(foo).data # results in: foo_json == { "foo": { # <- added by self.wrap_with_envelope on @post_dump "id": 1, "name": "FooBar" } } # and on deserialization, self.unwrap_envelope loads it correctly: foo = foo_serializer.load(foo_json).data isinstance(foo, Foo) == True """ # define this on your serializers to set the envelope name(s), # instead of relying on automatic naming based on the model name __envelop__ = { 'single': None, 'many': None, } def get_envelope_key(self, many): single_key = self.__envelop__.get('single', None) many_key = self.__envelop__.get('many', None) if not many and single_key: return single_key elif many and many_key: return many_key name = self.Meta.model.__name__ # JS tends to use camelCase, so that's what we use here by default key = name[0].lower() + name[1:] if many: return pluralize(key) return key @pre_load(pass_many=True) def unwrap_envelope(self, data, many): return data[self.get_envelope_key(many)] @post_dump(pass_many=True) def wrap_with_envelope(self, data, many): return {self.get_envelope_key(many): data}