Search code examples
djangojsonserializationtastypie

django-tastypie custom serialization for fetching only one entry


I have a model with a custom json serializer that performs some processing prior to dumping to json.

Now, when fetching a single obj i want to use the custom serializer from the model to fetch the entire object (with the processing mentioned above). When fetching a list i want to use the default serializer to fetch only the headers (render only the model fields).

I looked into three options

overriding obj_get

def obj_get(self, bundle, **kwargs):
        obj = ComplexModel.objects.get(pk=kwargs['pk'])
        return obj.to_serializable()

i got thrown with

{"error": "The object LONG JSON DUMP has an empty attribute 'description' and doesn't allow a default or null value."}

not sure why this is happening - the field description is nullable, Plus - why tastypie is checking validation for objects already in the database, and... while fetching ??

using dehydrate

 def dehydrate(self, bundle):
            return bundle.obj.to_serializable()

This is great but the cycle is executed before each object - so i cann't tell if I'm fetching a list or a single object. The result here is the full serizliazed objects whether it's a list or a single entry.

creating a custom serializer

  class CustomComplexSerializer(Serializer):
        def to_json(self, data, options=None):
            if isinstance(data,ComplexModel):
                data = data.to_serializable()
            return super(CustomComplexSerializer,self).to_json(data)

Same problem here, when fetching one entry the serializer accepts the obj in data.obj, when it's fetching a list it accepts a dict (odd...). I can check if bundle is an instance of dict as well - but testing for the type of ComplexModel felt awkward enough.

So what is the best way to implement a custom serialization for fetching only a single entry ?


Solution

  • Just for future reference, I think i found the right way to do this and it's by using full_dehydrate.

     def full_dehydrate(self, bundle, for_list=False):
            if not for_list:
                return bundle.obj.to_serializable()
            return super(ReportResource,self).full_dehydrate(bundle,for_list)