trubliphone
trubliphone

Reputation: 4504

Custom Django Rest Framework Serializer Field not running `to_representation()` if value is null

I would like a custom (read-only) serializer field that replaces the serialized value if it is None. I assumed that I could just overwrite to_representation(), but that doesn't seem to run. Here is some code:

models.py:

class Book(models.Model):
  title = models.CharField(max_length=255)
  rating = models.IntegerField(null=True)

serializers:

class ReplaceableSerializerField(serializers.ReadOnlyField):

  def to_representation(self, value):
    if value is None:
      return "this book sucks"
    return value

class BookSerializer(serializers.ModelSerializer):

  class Meta:
    model = Book
    fields = ("title", "rating",)

  rating = ReplaceableSerializerField(allow_null=True)

If I then do the following:

hamlet = Book(title="Hamlet")
BookSerializer(instance=hamlet).data

I get the following response:

{'title': 'Hamlet', 'rating', None}

Notice how the rating is None instead of "this book sucks".

Any idea on how to force to_representation() to run on null fields?

Upvotes: 7

Views: 2629

Answers (3)

Joao Paulo Rabelo
Joao Paulo Rabelo

Reputation: 185

I'm sorry for raising such old post with an answer, but for your specific case, you can simply have something along the lines of:

class ReplaceableSerializerField(serializers.ReadOnlyField):

  def to_representation(self, value):
    return value

class BookSerializer(serializers.ModelSerializer):

  class Meta:
    model = Book
    fields = ("title", "rating",)

  rating = ReplaceableSerializerField(default="this book sucks")

But then again, if the only thing you want to do is to replace the default value of your rating when it's empty and the rating itself is already a string, you could simply ignore the CustomField and go straight to:

class BookSerializer(serializers.ModelSerializer):

  class Meta:
    model = Book
    fields = ("title", "rating",)

  rating = serializers.CharField(default="this book sucks")

and you get a much cleaner code overall.

Upvotes: 0

Yoshi
Yoshi

Reputation: 1

My workaround is to override get_attribute(self, instance) method.

def get_attribute(self, instance):
    value = getattr(instance, self.source)
    if value is None:
        return "this book sucks"
    return value

djangorestframework 3.12.4

Upvotes: 0

ruddra
ruddra

Reputation: 51988

As far as I can understand from implementation, to_representation method does not get called if the value is None. So to avoid this problem, I think you can use SerializerMethodField. You can use it like this:

class BookSerializer(serializers.ModelSerializer):
  rating = serailizer.SerializerMethodField()

  class Meta:
    model = Book
    fields = ("title", "rating",)

  def get_rating(self, obj):
      if obj.rating == None:
         return "Something"
      return obj.rating

Upvotes: 3

Related Questions