Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify field names in serializer in Django Rest Framework

I have an object I'd like to serialize using DRF's serializers, but I'd like to normalize some field names. I thought I might be able to use the source attribute to achieve this:

user = { 'FirstName': 'John', 'LastName': 'Doe' }

serialized = UserSerializer(data=user)

class UserSerializer(serializers.Serializer):
    first_name = serializers.CharField(source="FirstName")
    last_name = serializers.CharField(source="LastName")

However, I'm not sure how to access the data object passed in - is there a way without creating a new method or some kind of complex super() call?

edit:

Use case: I'm hitting an API which returns values in CamelCase ('FirstName', 'LastName' etc) which I need to validate and modify key names to snake case. I was hoping I could use a standalone serializer, and transform the names in the serializer. I don't have a model for the data that must be transformed.

like image 934
Toby Avatar asked Nov 23 '18 19:11

Toby


Video Answer


2 Answers

Try this:

class UserSerializer(serializers.Serializer):
    FirstName = serializers.CharField(source="first_name")
    LastName = serializers.CharField(source="last_name")

serializing:

class Person:
    first_name = "first name"
    last_name = "last name"

person1 = Person()
serialized_data = UserSerializer(person1).data # = {"FirstName": "first name", "LastName": "last name"}

deserializing:

data = { 'FirstName': 'John', 'LastName': 'Doe' }
serializer = UserSerializer(data=data)
serializer.is_valid()
valid_deserialized_data = serializer.validated_data # = { 'first_name': 'John', 'last_name': 'Doe' }
like image 85
Ehsan Nouri Avatar answered Oct 20 '22 20:10

Ehsan Nouri


You can achieve this with properties on your Django model:

class Foo(models.model):
    bar = models.CharField(max_length=40)

    @property
    def sanitized_bar(self):
        print("Getting value")
        return self.bar.lower()



    @sanitized_bar.setter
    def sanitized_bar(self, value):
        self.bar = value.lower()

class FooSerializer(serializers.Serializer):
   bar = CharField(source='sanitized_bar')

Doing it this way gives you sanitized control on your DB if you need to use those models in management commands or elsewhere, in addition to your DRF interface.

You can also do a pre-save hook:

class Foo(models.model):
    def save(self, *args, **kwargs):
        if self.bar:
            self.bar = self.bar.lower()
        super().save(*args, **kwargs)
like image 43
Ross Rogers Avatar answered Oct 20 '22 20:10

Ross Rogers