Django REST Framework: agregar un campo adicional a ModelSerializer

Resuelto Neil asked hace 11 años • 11 respuestas

Quiero serializar un modelo, pero quiero incluir un campo adicional que requiere realizar algunas búsquedas en la base de datos en la instancia del modelo que se va a 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 puedes pasar un "contexto" adicional al serializador. ¿Es la respuesta correcta pasar el campo adicional en un diccionario de contexto?

Con ese enfoque, la lógica para obtener el campo que necesito no sería independiente de la definición del serializador, lo cual es ideal ya que cada instancia serializada necesitará my_field. En otra parte de la documentación de los serializadores DRF dice "los campos adicionales pueden corresponder a cualquier propiedad o invocables en el modelo". ¿Estoy hablando de "campos adicionales"?

¿Debo definir una función en Foola definición del modelo que devuelva my_fieldun valor y en el serializador conecto my_field a ese invocable? ¿Cómo se ve eso?

Feliz de aclarar la pregunta si es necesario.

Neil avatar Aug 23 '13 13:08 Neil
Aceptado

Creo SerializerMethodFieldque 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

J.P. avatar Aug 25 '2013 06:08 J.P.

Puede cambiar el método de su modelo a 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 versiones recientes de rest framework (probé 3.3.3), no es necesario cambiar a la propiedad. El método del modelo funcionará bien.

Wasil W. Siargiejczyk avatar Aug 23 '2013 06:08 Wasil W. Siargiejczyk