Reputation: 3311
I have a model with ImageField type below:
class Attendance(models.Model):
face_image = models.ImageField(, blank=True, null=True, storage=MediaStorage())
A serializer that is based on the model
class AttendanceSerializer(serializers.ModelSerializer):
class Meta:
model = Attendance
fields = ('id','face_image')
However if the imagefield is null, it shows like this
Its now showing like this in the json
{
"id": 1,
"face_image": null
}
It will show an output for face_image (ImageField) as null if it is None. What I would like is to substitute null to be an empty string like this ""
Upvotes: 21
Views: 16932
Reputation: 96
You can custumize a serializer field and use it as the default ModelSerializer field mapping for ImageField.
Note: The following code snippet should be loaded before you serializer class.
from rest_framework import serializers
from django.db import models
class MyImageField(serializers.ImageField):
def __init__(self, *args, **kwargs):
self.null_as_blank = kwargs.pop('null_as_blank', True)
if self.null_as_blank:
kwargs['allow_blank'] = True
super().__init__(*args, **kwargs)
def to_internal_value(self, data):
value = super().to_internal_value(data)
# Handle deserializer, change blank value back to null.
if self.null_as_blank and value == '':
value = None
return value
def to_representation(self, value):
value = super().to_internal_value(value)
if self.null_as_blank and value is None:
value = ''
return value
serializers.ModelSerializer.serializer_field_mapping[models.ImageField] = MyImageField
Upvotes: 1
Reputation: 2706
To add to JPG's answer, here is a mixin that allows re-using the logic of overriding the to_representation
method more easily. It also ensures that the values are None
not just falsy.
class ConvertNoneToStringSerializerMixin():
"""
Mixin to convert None to empty strings.
This must be added as the first inherited class. The property `Meta.none_to_str_fields` must
be defined in order for this to have any effect. This only applies to representations,
when we export our instance data, not when we acquire and validate data.
"""
def get_none_to_str_fields(self):
meta = getattr(self, 'Meta', None)
return getattr(meta, 'none_to_str_fields', [])
def to_representation(self, instance):
fields = self.get_none_to_str_fields()
data = super().to_representation(instance)
if not fields or not isinstance(data, dict):
return data
for field in fields:
if field in data and data[field] is None:
data[field] = ''
return data
This is how you would use it:
class AttendanceSerializer(ConvertNoneToStringSerializerMixin, serializers.ModelSerializer):
class Meta:
model = Attendance
fields = ('id', 'face_image')
none_to_str_fields = ('face_image', )
Also, for those who were wondering, we cannot override the to_representation
method of a Field
itself because the core implementation of Serializer
will skip calling to_representation
from the field when the value is None
. Therefore overriding the serializer is the only way this can be achieved.
Upvotes: 5
Reputation: 81
Code for iteration over all fields mentioned in the Serializer Meta:
def to_representation(self, instance):
data = super().to_representation(instance)
for key, value in data.items():
try:
if not value:
data[key] = ""
except KeyError:
pass
return data
Upvotes: 6
Reputation: 88539
Override the to_representation()
method of AttendanceSerializer
as,
class AttendanceSerializer(serializers.ModelSerializer):
class Meta:
model = Attendance
fields = ('id', 'face_image')
def to_representation(self, instance):
data = super().to_representation(instance)
if not data['face_image']:
data['face_image'] = ""
return data
I have lots of fields and its not really good idea that I repeat this code for all of them, isn't there a better way to do it for all fields?
class AttendanceSerializer(serializers.ModelSerializer):
class Meta:
model = Attendance
fields = ('id', 'face_image')
def to_representation(self, instance):
my_fields = {'field_1', 'field_2', 'field_3', 'field_4', 'field_5'}
data = super().to_representation(instance)
for field in my_fields:
try:
if not data[field]:
data[field] = ""
except KeyError:
pass
return data
Upvotes: 30
Reputation: 169051
You could use a SerializerMethodField.
class AttendanceSerializer(serializers.ModelSerializer):
face_image = serializers.SerializerMethodField()
class Meta:
model = Attendance
fields = ('id', 'face_image')
def get_face_image(self, instance):
return (instance.face_image.url if instance.face_image else '')
Upvotes: 8