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
Django Rest Framework and JSONField
提问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_native和from_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 内置DictField或ListField。
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',)

