JSONField でDjangoモデルが与えられた場合、 Django Rest Framework を使用してモデルをシリアライズおよびデシリアライズする正しい方法は何ですか?
私はすでにカスタム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)
しかし、partial=True
を使用してモデルを更新しようとすると、JSONFieldオブジェクトのすべてのフロートが文字列になります。
Django Rest Framework> = 3.3を使用している場合、JSONFieldシリアライザーは 現在含まれています です。これが正しい方法です。
Django Rest Framework <3.0を使用している場合は、gzeroneの答えを参照してください。
DRF 3.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()
また、バイナリデータをシリアル化する必要がある場合は、いつでもコピーできます 公式リリースコード
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
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とJSONFieldsを使用する
記録に関しては、PostgreSQLを使用していて、モデルフィールドがaDjango.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)
助けてくれてありがとう。これは私が最終的にそれをレンダリングするために使用するコードです
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を使用できます
serializers.py
from rest_framwork import serializers
class FinalSerializer(serializers.ModelSerializer):
class Meta:
model=Student
fields='__all__'
views.py
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
DRFはバイナリデータ用の組み込みフィールド「JSONField」を提供しますが、JSONペイロードは「binary」フラグをTrueに設定してからutf-8に変換し、JSONペイロードをロードする場合にのみ検証されます。 JSONFieldを作成した場合でも、エラーなしで両方を検証し、両方を検証します
class JSONSerializer(serializers.ModelSerializer):
"""
serializer for JSON
"""
payload = serializers.JSONField(binary=True)
MysqlのJSONFieldが必要な場合、これはDjango-mysqlで行われ、シリアライザーは先日[1]に修正されましたが、まだリリースされていません。
[1] https://github.com/adamchainz/Django-mysql/issues/35
追加:
'Django_mysql',
from Django_mysql.models import JSONField
class Something(models.Model):
(...)
parameters = JSONField()