Django (JSONField)和tastypie

7

我在mysql中有一个表,它的类型是TextField(django),使用JSONField。以下是我的模型:

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"}'

在数据库中,我可以看到:

{"data":"value"}

但是当使用curl检索数据时,我得到了类似这样的东西。
"{u'data': u'value'}"

我该怎样才能使Python的u'field'表示不出现在Tastypie的输出中?谢谢!

找到了问题所在 - 该字段从数据库中序列化为Unicode,并由Tastypie原样发送 - 为了解决这个问题,我在“load”中使用了Resource上的hydrate方法将其作为Python数据结构进行加载并发送到Tastypie。 - silviud
3
如果您能在回答中分享您解决问题的代码,那就太好了。然后请将其标记为被接受的答案。 - dan-klasson
4个回答

5
您看到的错误是由Tastypie将JSONField视为TextArea并在返回给调用者之前对JSONField返回的对象调用str()引起的。
另一种方法是使用fields.ApiFields来处理JSONField。这是因为fields.ApiFields不会对输入(hydrate())或输出(convert())进行任何转换。这正是我们想要的 - 底层的JSONField将把JSON对象转换为字符串以便在输入时持久化,并在输出时从字符串重新创建对象。因此,Tastypie不需要做任何事情。我的代码看起来有点像这样(基于OP的示例)-
class JSONField(fields.apiField):
    """ Wrapper over fields.apiField to make what we're doing here clear """
    pass

class MyModelResource(ModelResource):
    obj = JSONField('obj')

5
我像这样修复了这个问题:
def dehydrate_user_inputs(self, bundle):
    requirement = Requirement.objects.get(pk = bundle.obj.pk)
    user_inputs = json.dumps(requirement.user_inputs)
    return user_inputs

我的JSONField命名为user_inputs。需求是它所属的模型。

我感觉在这里进行查询有些奇怪,因为Tastypie已经为我完成了这项工作,但是这样做可以运行。如果有更好的解决方案,那就太好了。


5
你无需进行数据库查询,因为你的 Requirement 对象已经在 bundle.obj 中了。 你可以简化你的解决方案如下: <code> def dehydrate_user_inputs(self, bundle): return json.dumps(bundle.obj.user_inputs) </code> - tcmb
1
@tcmb 我认为你的评论是不正确的(至少在tastypie 0.11.1中是这样)。当你到达脱水阶段时,JSON对象已经被转换为Unicode(我假设是由tastypie完成的)。因此,在脱水点解决这个问题,你需要像kvnn所说的那样重新读取它。请参见我的答案,了解另一种方法(在水合点解决它)。 - John Lucas

4
请使用DictField:
obj = fields.DictField(attribute='obj')

这说明了,总是值得向下滚动并查看StackOverflow上的其他答案。这是一个很好的答案。我以前使用过obj = fields.ListField(attribute='obj'),但那是针对类似数组的数据,而这正是我需要的更像字典的数据。 - teewuane

1
我遇到了类似的问题,我的unicode字符串在API中以奇怪的格式返回(我认为是原始编码的字符串被返回而不是实际的utf-8字符)。无论如何,与其使用dehydrate方法重新查询,您最好在资源中使用自定义序列化器。这就是我使用的方法:
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)

然后在您的资源中:

class PlaceResource(ModelResource):
    class Meta:
        queryset = Place.objects.all()
        resource_name = 'place'
        serializer = JSONSerializer()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接