Prometeo
¿Cómo se agrega un campo que no es modelo en un ModelSerializer en DRF 3? es decir, agregar un campo que no existe en mi modelo real?
class TestSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="vote_detail")
non_field = serializers.CharField() # no corresponding model property.
class Meta:
model = vote_model
fields = ("url", "non_field")
def create(self, validated_data):
print(direction=validated_data['non_field'])
Pero DRF 3 me da el error:
Got AttributeError when attempting to get a value for field `non_field` on serializer `TestSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Test` instance.
Original exception text was: 'Test' object has no attribute 'non_field'.
Busqué en la pila DRF – ModelSerializer con un campo write_only que no es modelo y encontré algunas soluciones, pero estas se refieren a DRF 2 donde estoy usando DRF 3. ¿Hay una solución para esto en esta versión?
AJ Parr
class MySerializer(serializers.ModelSerializer):
write_only_char_field = serializers.CharField(write_only=True)
write_only_list_char_field = serializers.ListField(child=serializers.CharField(max_length=100, default=""), write_only=True)
empty_method_field = serializers.SerializerMethodField()
read_only_custom_model_field = serializers.CharField(source="custom_property", read_only=True)
def create(self, validated_data):
validated_data.pop('write_only_char_field', None)
validated_data.pop('write_only_list_char_field', None)
return super().create(validated_data)
los serializers.CharField(write_only=True)
y serializers.ListField(...)
es una buena solución para proporcionar datos adicionales a su .create()
y .update()
métodos, ya sea como una sola cadena o como una lista de cadenas (puede mezclar ListField
con otros tipos de campo de serializador).
Con este método, también puede definir def validate_write_only_char_field
implementar alguna validación rápida y sencilla.
serializers.SerializerMethodField()
le permite agregar algún campo personalizado de solo lectura a la salida de su serializador desde un método definido en el serializador.
los read_only_custom_model_field
usaría un método en su modelo para leer algunos datos, no estrictamente un campo de modelo, sino un método personalizado. Es decir
class MyModel(models.Model):
my_field = models.CharField(max_length=100)
@property
def custom_property(self):
return "Perform calculations, combine with related models, etc. etc."
-
Esta es la respuesta más completa, perfecto~
– Hola
13 de septiembre de 2018 a las 3:15
-
Y el único que encontré (demasiado tarde) sobre escribir solo campos que no son modelo. Eventualmente podrías hacer estallar las llaves en el
validate
método, tal vez más apropiado–Guillaume Lebreton
27 de septiembre de 2018 a las 7:51
-
Muchas gracias @ARJMP
– Prakash Kumar
24 de octubre de 2018 a las 10:19
-
write_only
es exactamente lo que necesitaba. Gracias– inostia
15 abr 2020 a las 21:47
-
Al usar el
write_only
solución que tuve que agregar el campo no modelo afields
. ¿Porqué es eso?– binny
29 de noviembre de 2021 a las 5:52
chandu
class Foo(models.Model):
. . .
@property
def my_field(self):
return stuff
. . .
Fuente:
Django REST Framework: agregar un campo adicional a ModelSerializer
-
Gracias, funciona, dado que lo agregamos en el
fields
lista.– Evidencia
24 de enero de 2017 a las 18:42
chandu
Solo un ejemplo podría ayudarte.
class ExtensibleModelSerializerOptions(serializers.SerializerOptions):
"""
Meta class options for ModelSerializer
"""
def __init__(self, meta):
super(ExtensibleModelSerializerOptions, self).__init__(meta)
self.model = getattr(meta, 'model', None)
self.read_only_fields = getattr(meta, 'read_only_fields', ())
self.non_native_fields = getattr(meta, 'non_native_fields', ())
class ExtensibleModelSerializer(serializers.ModelSerializer):
_options_class = ExtensibleModelSerializerOptions
def restore_object(self, attrs, instance=None):
"""
Deserialize a dictionary of attributes into an object instance.
You should override this method to control how deserialized objects
are instantiated.
"""
for field in self.opts.non_native_fields:
attrs.pop(field)
return super(ExtensibleModelSerializer, self).restore_object(attrs, instance)
Fuente:
https://github.com/tomchristie/django-rest-framework/issues/951
Como se mencionó, hay dos formas. (1) agregar una propiedad de modelo. (2) agregar un campo modelo. Siento que agregar una @propiedad al modelo se explicó bien en esta publicación. Si desea mantener sus modelos “delgados y eficientes”, use un campo Método. Sin embargo, la respuesta de Chandu omite algunos puntos cruciales:
class DeliveryItemSerializer(serializers.ModelSerializer):
product_name = serializers.SerializerMethodField(read_only=True)
def get_product_name(self, obj):
return obj.product.name
class Meta:
model = DeliveryItem
fields = (
(...your field names),
'product_name',)
- Establecer solo lectura
- El campo y el método correspondiente no tienen el mismo nombre. El nombre del método por defecto es
get_
nombre del campo. Si usa otro nombre use elmethod_name=method
argumento de nombre enSerializerMethodField()
chandu
class TestSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="vote_detail")
non_field = serializers.SerializerMethodField() # no corresponding model property.
class Meta:
model = vote_model
fields = ("url", "non_field")
def create(self, validated_data):
print(direction=validated_data['non_field'])
http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
o pasa por este enlace
-
non_field = serializers.serializers.SerializerMethodField() # sin propiedad de modelo correspondiente: elimine los serializadores adicionales. ?
– Liz
23 de febrero de 2016 a las 23:11
-
Estoy tratando de hacer exactamente lo mismo pero tengo un error que me dice que mi modelo no tiene este campo. ¿Alguien encontró una solución?
– ben
22 de noviembre de 2016 a las 16:31
-
Esta respuesta es incorrecta. Lo primero que dice en el enlace de arriba, django-rest-framework.org/api-guide/fields/…es que SerializerMethodField es un campo de solo lectura.
– kylebebak
4 de junio de 2019 a las 8:01
-
non_field = serializers.serializers.SerializerMethodField() # sin propiedad de modelo correspondiente: elimine los serializadores adicionales. ?
– Liz
23 de febrero de 2016 a las 23:11
-
Estoy tratando de hacer exactamente lo mismo pero tengo un error que me dice que mi modelo no tiene este campo. ¿Alguien encontró una solución?
– ben
22 de noviembre de 2016 a las 16:31
-
Esta respuesta es incorrecta. Lo primero que dice en el enlace de arriba, django-rest-framework.org/api-guide/fields/…es que SerializerMethodField es un campo de solo lectura.
– kylebebak
4 de junio de 2019 a las 8:01
github.com/tomchristie/django-resto-framework/issues/840
– chandu
2 de junio de 2015 a las 14:07
django-rest-framework.org/api-guide/fields/…
– chandu
2 de junio de 2015 a las 14:11
@chandu, entonces, ¿el problema continúa ya que no se solucionó en 3.0+ o ahora hay una solución para esto?
– Prometeo
2 de junio de 2015 a las 14:27
puede usar este método o el siguiente método django-rest-framework.org/api-guide/fields/…
– chandu
2 de junio de 2015 a las 14:29
Lo resolví usando un “ @property“ en el modelo de la respuesta que publicaste anteriormente. ¿Puedes publicar y responder para que pueda aceptar?
– Prometeo
2 de junio de 2015 a las 14:45