Creé ModelSerializer
y quiero agregar un campo personalizado que no es parte de mi modelo.
Encontré una descripción para agregar campos adicionales aquí e intenté lo siguiente:
customField = CharField(source='my_field')
Cuando agrego este campo y llamo a mi validate()
función, este campo no es parte del attr
dict. attr
contiene todos los campos del modelo especificados excepto los campos adicionales. Entonces, no puedo acceder a este campo en mi validación sobrescrita, ¿verdad?
Cuando agrego este campo a la lista de campos de esta manera:
class Meta:
model = Account
fields = ('myfield1', 'myfield2', 'customField')
luego customField
aparece un error porque no es parte de mi modelo, lo que es correcto porque quiero agregarlo solo para este serializador.
¿Hay alguna forma de agregar un campo personalizado?
Respuestas:
Está haciendo lo correcto, excepto que
CharField
(y los otros campos escritos) son para campos de escritura.En este caso, solo desea un campo simple de solo lectura, así que en su lugar use:
customField = Field(source='get_absolute_url')
fuente
.validate()
método para eliminar el atributo. Ver: django-rest-framework.org/api-guide/serializers.html#validation Eso haría lo que necesita, aunque realmente no entiendo el caso de uso, o por qué desea un campo de escritura que esté vinculado a un propiedad de solo lecturaget_absolute_url
?get_absolute_url
que acabo de copiar y paste'd que a partir de los documentos. Solo quiero un campo de escritura normal al que pueda acceder en elvalidate()
. Supuse que necesitaría elsource
atributo ...De hecho existe una solución sin tocar en absoluto el modelo. Puede utilizar los
SerializerMethodField
que le permiten conectar cualquier método a su serializador.class FooSerializer(ModelSerializer): foo = serializers.SerializerMethodField() def get_foo(self, obj): return "Foo id: %i" % obj.pk
fuente
SerializerMethodField
no lo son... para mayor claridad, 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 así:
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', )
fuente
perform_create(self, serializer)
,perform_update(self, serializer)
,perform_destroy(self, instance)
.aquí responde a tu pregunta. debe agregar a su cuenta modelo:
@property def my_field(self): return None
ahora puedes usar:
customField = CharField(source='my_field')
fuente: https://stackoverflow.com/a/18396622/3220916
fuente
Para mostrar
self.author.full_name
, recibí un error conField
. Funcionó conReadOnlyField
:class CommentSerializer(serializers.HyperlinkedModelSerializer): author_name = ReadOnlyField(source="author.full_name") class Meta: model = Comment fields = ('url', 'content', 'author_name', 'author')
fuente
Con la última versión de Django Rest Framework, necesita crear un método en su modelo con el nombre del campo que desea agregar.
class Foo(models.Model): . . . def foo(self): return 'stuff' . . . class FooSerializer(ModelSerializer): foo = serializers.ReadOnlyField() class Meta: model = Foo fields = ('foo',)
fuente
Estaba buscando una solución para agregar un campo personalizado de escritura a un serializador de modelo. Encontré este, que no se ha cubierto en las respuestas a esta pregunta.
Parece que realmente necesita escribir su propio serializador simple.
class PassThroughSerializer(serializers.Field): def to_representation(self, instance): # This function is for the direction: Instance -> Dict # If you only need this, use a ReadOnlyField, or SerializerField return None def to_internal_value(self, data): # This function is for the direction: Dict -> Instance # Here you can manipulate the data if you need to. return data
Ahora puede usar este serializador para agregar campos personalizados a un ModelSerializer
class MyModelSerializer(serializers.ModelSerializer) my_custom_field = PassThroughSerializer() def create(self, validated_data): # now the key 'my_custom_field' is available in validated_data ... return instance
Esto también funciona si el modelo
MyModel
realmente tiene una propiedad llamadamy_custom_field
pero desea ignorar sus validadores.fuente
MyModel
instancia.Después de leer todas las respuestas aquí, mi conclusión es que es imposible hacer esto limpiamente. Tienes que jugar sucio y hacer algo como crear un campo write_only y luego anular los métodos
validate
yto_representation
. Esto es lo que funcionó para mí:class FooSerializer(ModelSerializer): foo = CharField(write_only=True) class Meta: model = Foo fields = ["foo", ...] def validate(self, data): foo = data.pop("foo", None) # Do what you want with your value return super().validate(data) def to_representation(self, instance): data = super().to_representation(instance) data["foo"] = whatever_you_want return data
fuente