Anoop
Anoop

Reputation: 543

How to change the many to many relationship format in drf

This is my serializer class

class ProjectSerializer(ModelSerializer):
    created_by = SlugRelatedField(read_only=True, slug_field='email')
    updated_by = SlugRelatedField(read_only=True, slug_field='email')
    team = SlugRelatedField(many=True, read_only=True, slug_field='first_name')
    class Meta:
       model = Project
       exclude = ['deleted_at']

This is Models.py

class Project(MandatoryFields, Model):  
    project_name = models.CharField(max_length=255, blank=True)
    project_areas = models.CharField(max_length=255, blank=True)
    team = models.ManyToManyField(
        settings.AUTH_USER_MODEL, blank=True, related_name="%(app_label)s_%(class)s_team")
    project_manager = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True,
        related_name="%(app_label)s_%(class)s_project_manager")       
    start_date = models.DateField(null=True, blank=True)
    end_date = models.DateField(null=True, blank=True)

    REQUIRED_FIELDS = []

    def __str__(self):
        return self.project_name

I am getting response like this

"status": true,
    "data": [
        {
            "id": 1,
            "created_by": "[email protected]",
            "updated_by": "[email protected]",
            "project_manager": "[email protected]",
            "team": ["Rahul",
             "Anoop",
             ],
            "created_date": "2020-01-16T05:18:58.471601Z",
            "modified_date": "2020-01-16T05:18:58.471662Z",
            "project_name": "ABC",
            "project_areas": "ABC",
            "start_date": null,
            "end_date": null,
        },

My issue is the team is a many to many relationship with user model. I need to change the response of the field team . It need to return the id and the name in a dictionary format.

How can I change this

 "team": [
        {
            "id": 1,
            "name": "Rahul",
        },
        {
            "id": 2,
            "name": "Anoop",
        }
    ], 

Upvotes: 0

Views: 127

Answers (1)

JPG
JPG

Reputation: 88589

Create a Nested Serializer (TeamSerializer) and wire-up it in your ProjectSerializer as,

from django.contrib.auth import get_user_model


class TeamSerializer(serializers.ModelSerializer):
    name = serializers.CharField(source='first_name')

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


class ProjectSerializer(ModelSerializer):
    created_by = SlugRelatedField(read_only=True, slug_field='email')
    updated_by = SlugRelatedField(read_only=True, slug_field='email')
    team = TeamSerializer(many=True, read_only=True)

    class Meta:
        model = Project
        exclude = ['deleted_at']

I have used source argument too here, which used to specify the source of data to be pulled off.


Update-1

Use SerializerMethodField

from django.contrib.auth import get_user_model


class TeamSerializer(serializers.ModelSerializer):
    name = serializers.SerializerMethodField()

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

    def get_name(self, user):
        return '{} {}'.format(user.first_name, user.last_name)

Upvotes: 4

Related Questions