bruth/django-preserialize

Issue with ThumbnailerImageField (ImageField?)

hauru opened this issue · 7 comments

hauru commented

Hi,

I'm using Easy Thumbnails for managing resized versions of images. In my model i have a ThumbnailerImageField which stores a URL to the original image. When trying to serialize an instance of this model, i get the JSON exception:

<ThumbnailerImageFieldFile: ...> is not JSON serializable

ThumbnailerImageField extends Django's original ImageField and the Django-provided serialization mechanism works well in this case so i guess it may be a bug.

bruth commented

Hi @hauru. preserialize does not actually encode the data into JSON. It simply creates a data structure based on the arguments in the serialize function. So, if the types in the data structure cannot be encoded by the Django JSON encoder (and therefore the standard library decoder), then the encode may need to be extended to support this type.

hauru commented

Yeah, sorry for that. Thanks for the quick response. Actually i know it isn't supposed to serialize into JSON but it was late yesterday when i was testing it and, as it turns out, my mind was far from being clear.

What i did was to drop-in replace my own serializer, which also converts model instances to regular Python dictionaries. Resulting data is JSON-encoded later with a different function call (using Django's own encoder). I guess what i was expecting from preserialize was the output dictionary values to be plain Python objects. In case of an ImageField it would mean a regular string with URL. This way doing actual serialization (JSON, XML etc.) wouldn't involve dealing with model fields anymore.

bruth commented

No problem at all.

I guess what i was expecting from preserialize was the output dictionary values to be plain Python objects.

I understand the expectation. However, since arbitrary fields could be defined on a model it would be impossible to account for all cases. That being said, a possible approach would be to coerce objects to a primitive based on it's internal type.

One way of handling this right now, is to use a posthook which take the model instance and the serialized attributes to perform some processing, such as getting the path string for the image file.

bruth commented

The coercion could use the get_prep_value method on fields. For example, here is FileField and it returns a string.

hauru commented

That's what i eventually end up doing. Well, more or less.

In my case the difficulty with posthook is that it has to be provided separately for the parent model and for each of the "related" fields. It's inconvenient since i need the same common logic to be applied for all model instances (i have ImageFields in many interrelated models). I ended up modifying your code and adding a separate "global" posthook which gets propagated from the parent serialize call to subsequent calls for instance's querysets.

Thanks once again!

bruth commented

I have a couple of improvements in the works. #14 defines the Serializer class to encapsulate these options rather than needing to use globals. I also have a branch to use get_prep_value as discussed above.

On a side note, some of the CI tests are failing due to Django's AppRegistryNotReady error. I am less familiar with Django 1.7+ Any thoughts on this? The test script and tests package are pretty basic.

bruth commented

Looks like I figured it out. I was not calling django.setup() for versions greater than 1.7.