Roger Thomas
Roger Thomas

Reputation: 881

Delete Member of Many To Many Relationship Django Rest Framework

Given the following system

#  Models
class Team(models.Model):
    name = models.CharField(max_length=128)


class Player(models.Model):
    name = models.CharField(max_length=128)
    teams = models.ManyToManyField(Team)

#  Serializers
class PlayerSerializer(serializers.ModelSerializer):
    teams = serializers.PrimaryKeyRelatedField(many=True, queryset=League.objects.all(), required=False)

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

# Views
class TeamViewSet(viewsets.ModelViewSet):
    queryset = Team.objects.all()
    serializer_class = TeamSerializer

Basically a player can be in many teams

So the question is, how do I implement endpoints to manage the player-team relationship. Say we have two teams with ids 1, and 2 I create a player with

POST /players/ {'name': 'player1'} this player will have Id 1

I want to add player to teams 1 and 2, and then remove player from team 2

With this setup I can do PATCH /players/1/ {'teams': [1, 2]}

How do I now remove player1 from team 2?

Also, is using a patch request to add player1 to teams 1 and 2 the correct way to do this?

Upvotes: 3

Views: 3491

Answers (1)

aredzko
aredzko

Reputation: 1730

My favorite approach to this problem would be to create a detail route endpoint on your viewset made for this. Here's an example of how that might look:

# Views
class TeamViewSet(viewsets.ModelViewSet):
    queryset = Team.objects.all()
    serializer_class = TeamSerializer

    @action(methods=['delete'], detail=True)
    def remove_players_from_team(self, request):
        team = self.get_object()
        players_to_remove = request.data['players']
        # ...

From there, you could add your logic to remove players from the team. The endpoint would be something along the lines of: <base_url>/api/teams/<team_id>/remove_players_from_team and would expect the argument players and a request type of DELETE, which you can expect any number of ways.

This can be applied to also add players, and could be applied on the reverse relation if desired.

As for which method to allow, think about what's being done. If it's adding players, prefer a POST request. If it's removing them, prefer a DELETE. If you want them to be considered as updating, then use PATCH.

If you're interested in using this, check out the DRF documentation.

Upvotes: 5

Related Questions