How to set different permissions for GET and POST methods with ListCreateAPIView?

Question:

I would like to set IsAuthenticated permission for GET and IsTeamLeader permission for POST with ListCreateAPIView and ModelSerializer, but without having a unique permission that check the request method in has_permission, as suggested in these questions here and here.

How could I do that ?

@permission_classes([IsAuthenticated])
class ManagerListView(ListCreateAPIView):
    queryset = Manager.objects.all()
    serializer_class = ManagerSerializer


class IsTeamLeader(permissions.BasePermission):
    def has_permission(self, request, view):
        if Manager.objects.filter(pk=request.user.pk).exists():
            return Manager.objects.get(pk=request.user.pk).is_team_leader


class ManagerSerializer(serializers.ModelSerializer):
    password1 = serializers.CharField(write_only=True)
    password2 = serializers.CharField(write_only=True)
    fields = serializers.JSONField(write_only=True)

    def validate(self, data):
        if data['password1'] != data['password2']:
            raise serializers.ValidationError('Passwords must match.')
        return data

    def create(self, validated_data):
        data = {
            key: value for key, value in validated_data.items()
            if key not in ('password1', 'password2')
        }
        data['password'] = validated_data['password1']
        user = self.Meta.model.objects.create_user(**data)
        return user

    class Meta:
        model = Manager
        fields = ('id', 'email', 'first_name', 'last_name', 'username', 'role', 'is_team_leader', 'password1', 'password2', 'fields')
        read_only_fields = ('id', 'first_name', 'last_name', 'role', 'is_team_leader', 'address', 'contact')
Asked By: Florent

||

Answers:

You can do this by overriding get_permission ftn in your views class, if the method is GET you can return your expected permission class else you can return default it would be for POST method e.g:

    def get_permissions(self):
        self.permission_classes = [IsTeamLeader]
        if self.request.method == "GET":
            self.permission_classes = [IsAuthenticated]
        return super(ManagerListView, self).get_permissions()

let me know if it helps you.

As above will block the Browsable form in html view you can add one tricky condition and update the ftn. (not recommended)

    def get_permissions(self):
        self.permission_classes = [IsAuthenticated]
        if self.request.method == "POST" and self.request.data:
            self.permission_classes = [IsTeamLeader]
        return super(ManagerListView, self).get_permissions()
Answered By: Usman Arshad