Python Django Rest 框架和 JSONField

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22434869/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:56:45  来源:igfitidea点击:

Django Rest Framework and JSONField

pythondjangodjango-modelsdjango-rest-framework

提问by Tzach

Given a Django model with a JSONField, what is the correct way of serializing and deserializing it using Django Rest Framework?

给定一个带有JSONField的 Django 模型,使用Django Rest Framework对其进行序列化和反序列化的正确方法是什么?

I've already tried crating a custom serializers.WritableFieldand overriding to_nativeand from_native:

我已经尝试过创建自定义serializers.WritableField和覆盖to_nativefrom_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)

But when I try to updating the model using partial=True, all the floats in the JSONField objects become strings.

但是当我尝试使用 更新模型时partial=True,JSONField 对象中的所有浮点数都变成了字符串。

采纳答案by Mark Chackerian

If you're using Django Rest Framework >= 3.3, then the JSONField serializer is now included. This is now the correct way.

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

If you're using Django Rest Framework < 3.0, then see gzerone's answer.

如果您使用的是 Django Rest Framework < 3.0,请参阅 gzerone 的答案。

If you're using DRF 3.0 - 3.2 AND you can't upgrade AND you don't need to serialize binary data, then follow these instructions.

如果您使用的是 DRF 3.0 - 3.2 并且您无法升级并且您不需要序列化二进制数据,请按照这些说明进行操作。

First declare a field class:

首先声明一个字段类:

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

And then add in the field into the model like

然后在字段中添加到模型中

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

And, if you do need to serialize binary data, you can always the copy official release code

而且,如果你确实需要序列化二进制数据,你可以随时复制官方发布的代码

回答by gzerone

In 2.4.x:

在 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.

回答by David Dehghan

serializers.WritableField is deprecated. This works:

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

回答by jonalvarezz

Mark Chackerian script didn't work for me, I'd to force the json transform:

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

Works fine. Using DRF 3.15 and JSONFields in Django 1.8

工作正常。在 Django 1.8 中使用 DRF 3.15 和 JSONFields

回答by Jocelyn delalande

If and only if you know the first-level style of your JSON content (List or Dict), you can use DRF builtin DictFieldor ListField.

当且仅当您知道 JSON 内容的一级样式(List 或 Dict)时,您才能使用 DRF 内置DictFieldListField

Ex:

前任:

class MyModelSerializer(serializers.HyperlinkedModelSerializer):
    my_json_field = serializers.DictField()

It works fine, with GET/PUT/PATCH/POST, including with nested contents.

它工作正常,GET/PUT/PATCH/POST包括嵌套内容。

回答by Scott Smith

For the record, this "just works" now if you are using PostgreSQL, and your model field is adjango.contrib.postgres.JSONField.

作为记录,如果您使用的是 PostgreSQL,并且您的模型字段是django.contrib.postgres.JSONField.

I'm on PostgreSQL 9.4, Django 1.9, and Django REST Framework 3.3.2.

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

I have previously used several of the other solutions listed here, but was able to delete that extra code.

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

Example Model:

示例模型:

class Account(models.Model):
    id = UUIDField(primary_key=True, default=uuid_nodash)
    data = JSONField(blank=True, default="")

Example Serializer:

示例序列化程序:

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

Example View:

示例视图:

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']

回答by Daniel Levinson

If you're using mysql (haven't tried with other databases), using both DRF's new JSONFieldand Mark Chackerian's suggested JSONSerializerFieldwill save the json as a {u'foo': u'bar'}string. If you rather save it as {"foo": "bar"}, this works for me:

如果您使用的是 mysql(尚未尝试使用其他数据库),则同时使用 DRF 的 newJSONField和 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)

回答by Sérgio

If you want JSONField for mysql this is done in django-mysql and serializer was fixed some day ago [1], is not yet in any release.

如果你想要用于 mysql 的 JSONField,这是在 django-mysql 中完成的,并且序列化程序在几天前已经修复 [1],目前还没有任何版本。

[1] https://github.com/adamchainz/django-mysql/issues/353

[1] https://github.com/adamchainz/django-mysql/issues/353

setting.py

设置.py

add:

添加:

    'django_mysql',

models.py

模型.py

from django_mysql.models import JSONField

class Something(models.Model):
(...)
    parameters = JSONField()

回答by Deepak

DRF gives us inbuilt field 'JSONField' for binary data, but JSON payload is verified only when you set 'binary' flag True then it convert into utf-8 and load the JSON payload, else it only treat them as string(if invalid json is sent) or json and validate both without error even though you cretaed JSONField

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

class JSONSerializer(serializers.ModelSerializer):
    """
    serializer for JSON
    """
    payload = serializers.JSONField(binary=True)

回答by antikytheraton

Thanks by the help. This is the code i finally use for render it

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

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',)