How to change field name in Django REST Framework

I am trying to change Model field name in DRF Serializer like alias in SQL. I have tried different methods but cannot succeed.

models.py

class Park(models.Model):
    name = models.CharField(max_length=256)
    alternate_name = models.CharField(max_length=256, blank=True)
    objects = models.GeoManager()

    class Meta:
        db_table = u'p_park'

    def __unicode__(self):
        return '%s' % self.name

    def alias_alternate_name(self):
        return self.alternate_name

serializers.py

class ParkSerializer(serializers.ModelSerializer):

    location = serializers.Field(source='alias_alternate_name')
    #location = serializers.SerializerMethodField(source='alias_alternate_name')

    #alternate_name as location


    class Meta:
        model = Park
        fields = ('id', 'name', 'location')

I have also tried to add alias in Django Queryset but cannot changed.

Updated

This is the exception that i am facing

AttributeError at /ViewName/ 'module' object has no attribute 'Field'

How can I do this?


Solution 1:

There is a very nice feature in serializer fields and serializers in general called 'source' where you can specify source of data from the model field.

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.SomeSerializerField(source='alternate_name')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

Where serializers.SomeSerializerField can be serializers.CharField as your model suggests but can also be any of the other fields. Also, you can put relational fields and other serializers instead and this would still work like charm. ie even if alternate_name was a foreignkey field to another model.

class ParkSerializer(serializers.ModelSerializer):
    locations = AlternateNameSerializer(source='alternate_name', many=true)

    class Meta:
        model = Park
        fields = ('other_fields', 'locations')

class AlternateNameSerializer(serializers.ModelSerialzer):
    class Meta:
        model = SomeModel

This works with the creation, deletion, and modification requests too. It effectively creates one on one mapping of the field name in the serializer and field name in models.

Solution 2:

You can use serializers.SerializerMethodField:

Here is the model Park, which has name and alternate_name fields.

class Park(models.Model):
    name = models.CharField(max_length=256)
    alternate_name = models.CharField(max_length=256, blank=True)
    objects = models.GeoManager()

    class Meta:
        db_table = u'p_park'

    def __unicode__(self):
        return '%s' % self.name

Here is Serializer for Park Model, ParkSerializer. This changes the name of alternate_name to location.

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.SerializerMethodField('get_alternate_name')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

    def get_alternate_name(self, obj):
        return obj.alternate_name

Additionally, you can use serializers.CharField with source attribute:

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.CharField(source='other_fields')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

Django's __ notation to traverse foreign key also works:

location = serializers.CharField(source='OtherModel__other_fields')

The same principle applies if you want to change the return type on the API, so you can do serializers.DecimalField(source=...) and other field types as well.

This would however work only for read only fields.