Rename response fields django rest framework serializer
Asked Answered
O

4

15

I'm calling a simple get API using djangorestframework. My Model is

class Category(models.Model):
    category_id = models.AutoField(primary_key=True)
    category_name = models.CharField("Category Name", max_length = 30)
    category_created_date = models.DateField(auto_now = True, auto_now_add=False)
    category_updated_date = models.DateField(auto_now = True, auto_now_add=False)

    def __str__(self):
        return self.category_name

serializer.py

class CategorySerializer(serializers.ModelSerializer) :
    class Meta:
        model = Category
        fields = ['category_id', 'category_name']

def category_list(request):
    if request.method == 'GET':
        categories = Category.objects.all()
        serializer = CategorySerializer(categories, many=True)
        return Response(serializer.data)

It's working fine when i hit request on the URL and returning following response.

[
    {
        "category_id": 1,
        "category_name": "ABC"
    }
]

i want to change the response field names as it's for my DB only and don't want to disclose in response. If i change the name in serializer class than it's giving no field match error.

Also i want to customise other params like above response in response object with message and status like below.

{
status : 200,
message : "Category List",
response : [
        {
            "id": 1,
            "name": "ABC"
        }
    ]
}

Need a proper guide and flow. Experts help.

Osteoporosis answered 5/9, 2016 at 6:3 Comment(1)
check this #22958558Discharge
R
41

First of all using category_ in field names is redundant. Because you are already assigning this fields to Category model, and by doing this you are creating "namespace" for this fields.

class Category(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField("Category Name", max_length = 30)
    created_date = models.DateField(auto_now = True, auto_now_add=False)
    updated_date = models.DateField(auto_now = True, auto_now_add=False)

    def __str__(self):
        return self.name

Second In django id AutoField is created automatically why would you need set it explicitly?

And answering your question There is source parameter in serializer fields.

class CategorySerializer(serializers.ModelSerializer):
    renamed_id = serializers.IntegerField(source='category_id')
    renamed_name = serializers.CharField(source='category_name')

    class Meta:
        model = Category
        fields = ['renamed_id', 'renamed_name']

And than you can change your response manually

from rest_framework import status

def category_list(request):
    if request.method == 'GET':
        categories = Category.objects.all()
        serializer = CategorySerializer(categories, many=True)
        response = {
            'status': status.HTTP_200_OK,
            'message' : "Category List",
            'response' : serializer.data
        }
        return Response(response)
Remount answered 5/9, 2016 at 6:46 Comment(6)
Tried but its giving AssertionError : The field 'renamed_id' was declared on serializer CategorySerializer, but has not been included in the 'fields' option.Osteoporosis
You need to just change fields parameter in Meta. See updated answer.Remount
Working. Thank you. Can you let me know which is the best practice to write customising response code. I mean to write in serializers.py or views.py?Osteoporosis
It depends on what you are trying to achieve. The best way would be write Class Based View which than can subclassed for reuse.Remount
It's working for get request but when i run a curl request for PUT it fails curl -X PUT localhost:8000/api/add-category/4 -d "category_name=xyz" It works fine for PUT when i don't rename the fieldsOsteoporosis
@PinankLakhani you need to write custom create and update methods on your serializer. django-rest-framework.org/api-guide/serializers/… where you would put data into real fields. instance.category_name = validated_data.get('renamed_name', instance.category_name)Remount
S
2

You can override to_representation function in serializer.Check the following code you can update data dictionary as you want.

class CategorySerializer(serializers.ModelSerializer) :
    class Meta:
        model = Category
        fields = ['category_id', 'category_name']
    def to_representation(self, instance):
        data = super(CategorySerializer, self).to_representation(instance)
        result_data={"status" : 200,"message" : "Category List"}
        result_data["response"]=data
        return result_data
Swipple answered 5/9, 2016 at 6:13 Comment(1)
It's adding in each object [ { "status": 200, "message": "Category List", "response": { "category_id": 1, "category_name": "Educational News" } }, { "status": 200, "message": "Category List", "response": { "category_id": 2, "category_name": "Death News" } }, ]Osteoporosis
I
2

You can just wrap it up in json. This is the way you render the way you want:

from django.http import HttpResponse
import json

def category_list(request):
    if request.method == 'GET':
        categories = Category.objects.all()
        serializer = CategorySerializer(categories, many=True)
        response = {'code: 200, 'message': 'Category List', 'response': serializer.data}
        return HttpResponse(json.dumps(response), mimetype='application/json')

This is the way you can rename your fields:

class CategorySerializer(serializers.ModelSerializer):
    name = serializers.CharField(source='category_name')

    class Meta:
        model = Category
        fields = ['category_id', 'name']

This is the docs for serializing with different names.

Ideomotor answered 5/9, 2016 at 6:13 Comment(8)
Now it's giving me following error File "/Users/smartSense/Pinank/Django/Work/MadhaparDemo/MadhaparDemo/ Category/urls.py", line 3, in <module> from .views import category_list File "/Users/smartSense/Pinank/Django/Work/MadhaparDemo/MadhaparDemo/ Category/views.py", line 15 response = {'code: 200, 'message': 'Category List', response: serializer.data}Osteoporosis
@PinankLakhani i am sorry, i changed that line a bit, try itIdeomotor
Working But still i can't import simplejson. Also i want to rename the field names tooOsteoporosis
@PinankLakhani you do this with json package(updated answer). What do you mean by renaming fields? You can do this in serializerIdeomotor
Tried but its giving AssertionError : The field 'name' was declared on serializer CategorySerializer, but has not been included in the 'fields' option.Osteoporosis
Working. Thank you. Can you let me know which is the best practice to write customising response code. I mean to write in serializers.py or views.py?Osteoporosis
@PinankLakhani it's really depends, because what are you trying to achive? Is it like HTTP response code or what? I believe it's not the best way to pass code in json object, you need to put that code in HTTP headerIdeomotor
It's working for get request but when i run a curl request for PUT it fails curl -X PUT localhost:8000/api/add-category/4 -d "category_name=xyz" It works fine for PUT when i don't rename the fieldsOsteoporosis
R
1

In Django 2.1.1 if you are using a viewset, you can customize the other parts of your response by overriding the .list() action like this

from rest_framework import status
from django.http import HttpResponse
import json

class CategoryViewset(viewsets.ReadOnlyModelViewSet):
    categories = Category.objects.all()

    def list(self, request):
        if request.method == 'GET':
            serializer = CategorySerializer(self.categories, many=True)
            response = {
                'status': status.HTTP_200_OK,
                'message' : "Category List",
                'response' : serializer.data,
            }
            return HttpResponse(json.dumps(response), content_type='application/json')
Roid answered 8/10, 2018 at 17:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.