t29mato
t29mato

Reputation: 145

how I can set ID in Django REST Framework JSON:API response?

I am using Django REST Framework JSON:API. Then, I want to set ID in the response.

I know the response gets ID from Django model instance. But, if I set the instance to the serializer, the ID will be null.

Example

class Tag(models.Model):
    name = models.CharField(max_length=64, unique=True)
class TagSerializer(serializers.Serializer):
    name = serializers.CharField()
class TagDetailView(views.APIView):
    def get(self, request, pk):
        tag = Tag.objects.get(pk=pk)
        serializer = TagSerializer(data={"name": tag.name, "memo": "memo"})
        serializer.is_valid(raise_exception=True)
        return Response(data=serializer.data, status=200)

Expected

{
    "data": {
        "type": "TagDetailView",
        "id": 1,
        "attributes": {
            "name": "name",
            "memo": "memo"
        }
    }
}

As-Is


{
    "data": {
        "type": "TagDetailView",
        "id": null, //  I WANT TO SET THE ID HERE
        "attributes": {
            "name": "name",
            "memo": "memo"
        }
    }
}

Upvotes: 0

Views: 750

Answers (1)

Nikita
Nikita

Reputation: 436

Firstly, you're passing initial data of serializer to your Response. In fact, you don't use your TagSerializer to serialize data from model instance to json.

Secondly, you have Tag model, so try to use serializers.ModelSerializer instead of serializers.Serializer.

To solve your problem, I'd do following:

  1. Change your serializer
class TagSerializer(serializers.ModelSerializer):
    name = serializers.CharField()
    memo = serializers.SerializerMethodField(method_name="get_memo")  # if you want to add some custom field which is not in your model

    class Meta:
        model = Tag
        fields = "__all__"
   
    def get_memo(self, obj: Tag) -> str:
        return "memo"
  1. Change a bit your APIView
from typing import Optional


class TagDetailView(views.APIView):
    def get(self, request, pk):
        tag: Optional[Tag] = Tag.objects.filter(pk=pk).first()
        if tag is None:
            return Response(data={}, status=404)
        data = TagSerializer(tag).data # passing instance of Tag to serializer
        return Response(data=data, status=200)

So, now you should have "id" in your response as far as we provided fields = "__all__" for TagSerializer

Upvotes: 1

Related Questions