example - Marco Django REST: agregar campo adicional a ModelSerializer
django rest framework serializer (6)
Como Chemical Programer dijo en este comentario , en el último DRF puedes hacerlo así:
class FooSerializer(serializers.ModelSerializer):
extra_field = serializers.SerializerMethodField()
def get_extra_field(self, foo_instance):
return foo_instance.a + foo_instance.b
class Meta:
model = Foo
fields = (''extra_field'', ...)
http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
Quiero serializar un modelo, pero quiero incluir un campo adicional que requiera realizar algunas búsquedas en la base de datos en la instancia del modelo que se serializará:
class FooSerializer(serializers.ModelSerializer):
my_field = ... # result of some database queries on the input Foo object
class Meta:
model = Foo
fields = (''id'', ''name'', ''myfield'')
¿Cuál es la forma correcta de hacer esto? Veo que puede pasar un "contexto" adicional al serializador, ¿es la respuesta correcta para pasar en el campo adicional en un diccionario de contexto? Con ese enfoque, la lógica de obtener el campo que necesito no sería independiente con la definición del serializador, que es ideal ya que cada instancia serializada necesitará my_field
. En otra parte de la documentación de los serializadores DRF, says "los campos adicionales pueden corresponder a cualquier propiedad o pueden llamarse en el modelo". ¿Hay campos adicionales de lo que estoy hablando? ¿Debería definir una función en la definición de modelo de Foo
que devuelva my_field
value, y en el serializador conecte my_field a ese callable? ¿Cómo se ve eso?
Gracias de antemano, feliz de aclarar la pregunta si es necesario.
Con la última versión de Django Rest Framework, debe crear un método en su modelo con el nombre del campo que desea agregar. No es necesario que @property
y source=''field''
@property
un error.
class Foo(models.Model):
. . .
def foo(self):
return ''stuff''
. . .
class FooSerializer(ModelSerializer):
foo = serializers.ReadOnlyField()
class Meta:
model = Foo
fields = (''foo'',)
Creo que SerializerMethodField es lo que estás buscando:
class FooSerializer(serializers.ModelSerializer):
my_field = serializers.SerializerMethodField(''is_named_bar'')
def is_named_bar(self, foo):
return foo.name == "bar"
class Meta:
model = Foo
fields = (''id'', ''name'', ''my_field'')
http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
Mi respuesta a una pregunta similar ( here ) podría ser útil.
Si tiene un Método de modelo definido de la siguiente manera:
class MyModel(models.Model):
...
def model_method(self):
return "some_calculated_result"
Puede agregar el resultado de llamar a dicho método a su serializador de la siguiente manera:
class MyModelSerializer(serializers.ModelSerializer):
model_method_field = serializers.CharField(source=''model_method'')
ps Dado que el campo personalizado no es realmente un campo en su modelo, generalmente querrá que sea de solo lectura, así:
class Meta:
model = MyModel
read_only_fields = (
''model_method_field'',
)
Puede cambiar el método de su modelo a la propiedad y usarlo en el serializador con este enfoque.
class Foo(models.Model):
. . .
@property
def my_field(self):
return stuff
. . .
class FooSerializer(ModelSerializer):
my_field = serializers.ReadOnlyField(source=''my_field'')
class Meta:
model = Foo
fields = (''my_field'',)
Editar: con las versiones recientes de rest framework (probé 3.3.3), no es necesario cambiar a la propiedad. El método del modelo funcionará bien.
si desea leer y escribir en su campo adicional, puede usar un nuevo serializador personalizado, que amplía serializadores.Serializador, y úselo de esta manera
class ExtraFieldSerializer(serializers.Serializer):
def to_representation(self, instance): # this would have the same as body as in a SerializerMethodField
return ''my logic here''
def to_internal_value(self, data):
return ''Any python object made with data: %s'' % data
class MyModelSerializer(serializers.ModelSerializer):
my_extra_field = ExtraFieldSerializer(source=''*'')
class Meta:
model = MyModel
fields = [''id'', ''my_extra_field'']
Yo uso esto en campos anidados relacionados con alguna lógica personalizada