with update instalar framework foreign create python django django-models django-rest-framework

python - update - Django Rest Framework y JSONField



partial update django rest framework (10)

DRF nos da el campo incorporado ''JSONField'' para datos binarios, pero la carga útil JSON solo se verifica cuando configuramos el indicador ''binario'' True luego convierte a utf-8 y carga la carga JSON; de lo contrario, solo los trata como cadena (si no es válido) se envía) o json y valida ambos sin error a pesar de que cretaste JSONField

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

Dado un modelo de Django con un campo JSONField , ¿cuál es la forma correcta de serializarlo y deserializarlo usando Django Rest Framework ?

Ya he intentado crear un serializers.WritableField personalizado. to_native y from_native to_native y 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)

Pero cuando trato de actualizar el modelo usando partial=True , todos los flotadores en los objetos JSONField se convierten en cadenas.


El guión de Mark Chackerian no funcionó para mí, forzaría la transformación 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

Funciona bien. Usando DRF 3.15 y JSONFields en Django 1.8


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


Gracias por la ayuda. Este es el código que finalmente uso para renderizarlo

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


Para el registro, esto "simplemente funciona" ahora si está usando PostgreSQL, y su campo de modelo es un django.contrib.postgres.JSONField .

Estoy en PostgreSQL 9.4, Django 1.9 y Django REST Framework 3.3.2.

Anteriormente utilicé varias de las otras soluciones enumeradas aquí, pero pude eliminar ese código adicional.

Modelo de ejemplo:

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

Ejemplo de serializador:

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

Vista de ejemplo:

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


Si desea JSONField para mysql esto se hace en django-mysql y el serializador se arregló hace un día [1], todavía no se encuentra en ninguna versión.

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

setting.py

añadir:

''django_mysql'',

models.py

from django_mysql.models import JSONField class Something(models.Model): (...) parameters = JSONField()


Si está utilizando Django Rest Framework> = 3.3, entonces el serializador JSONField ahora está incluido . Esta es ahora la forma correcta.

Si está utilizando Django Rest Framework <3.0, entonces vea la respuesta de gzerone.

Si está utilizando DRF 3.0 - 3.2 Y no puede actualizar Y no necesita serializar datos binarios, siga estas instrucciones.

Primero declara una clase de campo:

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

Y luego agregue en el campo en el modelo como

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

Y, si necesita serializar datos binarios, siempre puede copiar el código de versión oficial


Si está utilizando mysql (no lo ha intentado con otras bases de datos), usar el nuevo JSONField DRF y el JSONSerializerField sugerido por Mark Chackerian guardará el json como una {u''foo'': u''bar''} . Si prefiere guardarlo como {"foo": "bar"} , esto funciona para mí:

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)


Si, y solo si conoce el estilo de primer nivel de su contenido JSON (List o Dict), puede usar DRF DictField o ListField .

Ex:

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

Funciona bien, con GET/PUT/PATCH/POST , incluso con contenido anidado.


serializers.WritableField está en desuso. Esto funciona:

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