Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django (JSONField) and tastypie

I have a table into mysql that is the type TextField (django) by using the JSONField. This is how my model looks

from django.db import models
from json_field import JSONField

class Model(models.Model):
   obj     = JSONField()

The value I send via tastypie is

json_string = '{"data":"value"}'

Into the database I can see

{"data":"value"}

But when retrive the data with curl I get something like this

"{u'data': u'value'}"

What I can do to not have the python u'field' representation into the tastypie's output ?

thanks!

like image 336
silviud Avatar asked Jan 17 '13 19:01

silviud


4 Answers

I fixed this issue like so:

def dehydrate_user_inputs(self, bundle):
    requirement = Requirement.objects.get(pk = bundle.obj.pk)
    user_inputs = json.dumps(requirement.user_inputs)
    return user_inputs

My JSONField is named user_inputs. Requirement is the model that it belongs to.

I feel weird doing a Query here when Tastypie has already done so for me, but, this works. I'd love if there are better solutions.

like image 184
kvnn Avatar answered Nov 02 '22 14:11

kvnn


The error you're seeing is caused by Tastypie treating the JSONField like a TextArea and calling str() on the object JSONField returns before returning it to the caller.

Another approach is to use fields.ApiFields for the JSONField. This works because fields.ApiFields does not perform any conversions on either the way in (hydrate()) or way out (convert()). This is exactly what we want - the underlying JSONField will convert the JSON object to a string for persistence on the way in and recreate the object from the string on the way out. Thus, tastypie does not need to do anything. My code looks a bit like this (class/variable names based on OP's example) -

class JSONField(fields.apiField):
    """ Wrapper over fields.apiField to make what we're doing here clear """
    pass

class MyModelResource(ModelResource):
    obj = JSONField('obj')
like image 4
John Lucas Avatar answered Nov 02 '22 15:11

John Lucas


Use DictField:

obj = fields.DictField(attribute='obj')
like image 3
Ilya Baryshev Avatar answered Nov 02 '22 15:11

Ilya Baryshev


I was running into similar problems where my unicode strings would be returned in a weird format in the API (I think the raw encoded strings were returned as opposed to the actual utf-8 characters).

Anyway instead of using the dehydrate method and re-doing the query, you are better off with a custom serializer in your resources.

This is what I used:

class JSONSerializer(Serializer):
    '''using the standard json library for better unicode support,
       also note django.utils.simplejson, used in the standard Tastypie serializer, 
       is set for depreciation'''

    def to_json(self, data, options=None):
        options = options or {}
        data = self.to_simple(data, options)
        return json.dumps(data)

then in your resources:

class PlaceResource(ModelResource):
    class Meta:
        queryset = Place.objects.all()
        resource_name = 'place'
        serializer = JSONSerializer()
like image 1
gterzian Avatar answered Nov 02 '22 15:11

gterzian