Python Django Rest框架和JSONField

Python Django Rest框架和JSONField,python,django,django-models,django-rest-framework,Python,Django,Django Models,Django Rest Framework,给定一个带有a的Django模型,使用a序列化和反序列化它的正确方法是什么 我已经尝试装入自定义的序列化程序。WritableField并将重写为\u native和从\u native: from json_field.fields import JSONEncoder, JSONDecoder from rest_framework import serializers class JSONFieldSerializer(serializers.WritableField): de

给定一个带有a的Django模型,使用a序列化和反序列化它的正确方法是什么

我已经尝试装入自定义的
序列化程序。WritableField
并将
重写为\u native
从\u native

from json_field.fields import JSONEncoder, JSONDecoder
from rest_framework import serializers

class JSONFieldSerializer(serializers.WritableField):
    def to_native(self, obj):
    return json.dumps(obj, cls = JSONEncoder)

    def from_native(self, data):
        return json.loads(data, cls = JSONDecoder)
但是,当我尝试使用
partial=True
更新模型时,JSONField对象中的所有浮动都会变成字符串。

在2.4.x中:

from rest_framework import serializers # get from https://gist.github.com/rouge8/5445149

class WritableJSONField(serializers.WritableField):
    def to_native(self, obj):
        return obj


class MyModelSerializer(serializers.HyperlinkedModelSerializer):
    my_json_field = WritableJSONField() # you need this.

serializers.WritableField已弃用。这项工作:

from rest_framework import serializers
from website.models import Picture


class PictureSerializer(serializers.HyperlinkedModelSerializer):
    json = serializers.SerializerMethodField('clean_json')

    class Meta:
        model = Picture
        fields = ('id', 'json')

    def clean_json(self, obj):
        return obj.json

如果您使用的是Django Rest Framework>=3.3,那么JSONField序列化程序是。现在这是正确的方法


如果您使用的是Django Rest框架<3.0,那么请参阅gzerone的答案

如果您使用的是DRF3.0-3.2,并且无法升级,并且不需要序列化二进制数据,那么请按照以下说明操作

首先声明一个字段类:

from rest_framework import serializers

class JSONSerializerField(serializers.Field):
    """ Serializer for JSONField -- required to make field writable"""
    def to_internal_value(self, data):
        return data
    def to_representation(self, value):
        return value
然后将字段添加到模型中,如

class MySerializer(serializers.ModelSerializer):
    json_data = JSONSerializerField()

而且,如果您确实需要序列化二进制数据,您可以随时复制Mark Chackerian脚本,因为它对我不起作用,我会强制进行json转换:

import json

class JSONSerializerField(serializers.Field):
    """ Serializer for JSONField -- required to make field writable"""

    def to_internal_value(self, data):
        json_data = {}
        try:
            json_data = json.loads(data)
        except ValueError, e:
            pass
        finally:
            return json_data
    def to_representation(self, value):
        return value

很好。使用Django 1.8中的DRF 3.15和JSonfield如果并且仅当您知道JSON内容的第一级样式(列表或Dict),您可以使用DRF内置或

例:

它可以很好地使用
GET/PUT/PATCH/POST
,包括嵌套的内容。

对于记录,如果您使用的是PostgreSQL,那么这个“仅起作用”,并且您的模型字段是一个
django.contrib.postgres.JSONField

我使用的是PostgreSQL 9.4、Django 1.9和Django REST Framework 3.3.2

我以前使用过这里列出的其他几种解决方案,但能够删除额外的代码

示例模型:

class Account(models.Model):
    id = UUIDField(primary_key=True, default=uuid_nodash)
    data = JSONField(blank=True, default="")
示例序列化程序:

class AccountSerializer(BaseSerializer):
    id = serializers.CharField()
    class Meta:
        model = Account
        fields = ('id','data')
示例视图:

class AccountViewSet(
    viewsets.GenericViewSet,
    mixins.CreateModelMixin,      
    mixins.RetrieveModelMixin,
    mixins.ListModelMixin,
    mixins.UpdateModelMixin,
    mixins.DestroyModelMixin
): 
    model = Account
    queryset = Account.objects.all()
    serializer_class = AccountSerializer
    filter_fields = ['id', 'data']
如果您使用的是mysql(还没有尝试过其他数据库),那么使用DRF的新
JSONField
和Mark Chackerian建议的
JSONSerializerField
将json保存为
{u'foo':u'bar'}
字符串。 如果您更愿意将其保存为
{“foo”:“bar”}
,这对我很有用:

import json

class JSONField(serializers.Field):
    def to_representation(self, obj):
        return json.loads(obj)

    def to_internal_value(self, data):
        return json.dumps(data)

如果您想使用JSONField for mysql,这是在django mysql中完成的,并且serializer在前一天已经修复[1],还没有发布

[1]

setting.py 加:

    'django_mysql',
models.py DRF为我们提供了二进制数据的内置字段“JSONField”,但JSON 只有当您将“binary”标志设置为True,然后将其转换为utf-8并加载JSON有效负载时,才会验证有效负载,否则仅验证有效负载 将它们视为字符串(如果发送了无效的json)或json,并验证两者 即使您创建了JSONField,也不会出错


谢谢你的帮助。这是我最后用来渲染它的代码

class JSONSerializerField(serializers.Field):
    """Serializer for JSONField -- required to make field writable"""

    def to_representation(self, value):
        json_data = {}
        try:
            json_data = json.loads(value)
        except ValueError as e:
            raise e
        finally:
            return json_data

    def to_internal_value(self, data):
        return json.dumps(data)

class AnyModelSerializer(serializers.ModelSerializer):
    field = JSONSerializerField()

    class Meta:
        model = SomeModel
        fields = ('field',)

要从请求序列化数据,可以使用serializers.ModelSerializer

序列化程序.py

from rest_framwork import serializers
class FinalSerializer(serializers.ModelSerializer):
class Meta:
    model=Student
    fields='__all__'
import io
from yourappname.serializers import FinalSerializer #replace your app name
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser,MultiPartParser,FormParser
from rest_framework.response import Response


class DataList(APIView):


    parser_classes = (JSONParser,MultiPartParser,FormParser) #If you are using postman
    renderer_classes = (JSONRenderer,)
    #Serialize
    def get(self,request,format=None):
        all_data=Student.objects.all()
        serializer=FinalSerializer(all_data,many=True)
        return Response(serializer.data)#Will return serialized json data,makes sure you have data in your model
    #Deserialize
    #Not tried this function but it will work
    #from django documentation
    def djson(self,request,format=None):
        stream = io.BytesIO(json)
        data = JSONParser().parse(stream)
        serializer = FinalSerializer(data=data)
        serializer.is_valid()
        serializer.validated_data
视图.py

from rest_framwork import serializers
class FinalSerializer(serializers.ModelSerializer):
class Meta:
    model=Student
    fields='__all__'
import io
from yourappname.serializers import FinalSerializer #replace your app name
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser,MultiPartParser,FormParser
from rest_framework.response import Response


class DataList(APIView):


    parser_classes = (JSONParser,MultiPartParser,FormParser) #If you are using postman
    renderer_classes = (JSONRenderer,)
    #Serialize
    def get(self,request,format=None):
        all_data=Student.objects.all()
        serializer=FinalSerializer(all_data,many=True)
        return Response(serializer.data)#Will return serialized json data,makes sure you have data in your model
    #Deserialize
    #Not tried this function but it will work
    #from django documentation
    def djson(self,request,format=None):
        stream = io.BytesIO(json)
        data = JSONParser().parse(stream)
        serializer = FinalSerializer(data=data)
        serializer.is_valid()
        serializer.validated_data

我建议不要使用JSONField作为类名,因为它会与另一个class.fixmycode冲突,谢谢您对类名的建议。嗯…,这只是一个示例代码,它是从中复制的,所以您可以随意更改它。但是我认为@Tzach,'jsonfielserializer'对于'serializers.writeablefield'的子类不是一个合适的名称。看起来JSonfielSerializer和MyModelSerializer是相同的东西。希望听到您的意见。谢谢@gzone的评论。我承认我没有太注意新的类名。只是不想引起冲突。
jsonwriteablefield
对您来说更合适吗?或者writeablejsonfield,;)这仅对Django Rest Framework版本2有效。对于版本3,请参见Mark Chackerian的答案。是。如果您有一个要序列化的对象,您只需要读取它。这不会修改您正在序列化的原始对象。您如何将此序列化器字段与模型的JSonfield集成?你使用ModelSerializer吗?我使用的是
序列化程序。序列化程序
,但是使用
ModelSerializer
应该可以工作。注意,这确实适用于使用DRF 3.2的
ModelSerializer
。奇怪的是,它的排名很低。在客户端,我必须用补丁传递{“field”:JSON.stringify(data),…}。默认jquery$.ajax调用将每个值分解为长键,如“field[key1][key2][etc]”:value。
import io
from yourappname.serializers import FinalSerializer #replace your app name
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser,MultiPartParser,FormParser
from rest_framework.response import Response


class DataList(APIView):


    parser_classes = (JSONParser,MultiPartParser,FormParser) #If you are using postman
    renderer_classes = (JSONRenderer,)
    #Serialize
    def get(self,request,format=None):
        all_data=Student.objects.all()
        serializer=FinalSerializer(all_data,many=True)
        return Response(serializer.data)#Will return serialized json data,makes sure you have data in your model
    #Deserialize
    #Not tried this function but it will work
    #from django documentation
    def djson(self,request,format=None):
        stream = io.BytesIO(json)
        data = JSONParser().parse(stream)
        serializer = FinalSerializer(data=data)
        serializer.is_valid()
        serializer.validated_data