'Endpoints sharing part of an URL

I'm currently building an API with Django Rest Framework and I want to have two viewsets. One related to my User model, and one single route to verify a User email (you POST the currently-valid token to the endpoint). So it looks like this:

  • UserViewSet, which allows POST, GET, PUT, PATCH, DELETE
  • VerifyUserViewSet, which only allows POST

In my router, here's my config:

router = routers.DefaultRouter()
router.register("users", UserViewSet, "users")
router.register("users/verify", VerifyUserViewset, "users/verify")

My problem is as follows: "users/verify" allows a GET request (when it shouldn't) because it is targeting the "users" endpoint with "request" as the user id.

If I change the order in my router, then "users" only accept POST because the endpoints targets "users/verify". This seems to be happening because they share the same url part "users".

Is there a way to bypass this behavior so that they don't overlap without changing the endpoints url?

Thanks

EDIT

Serializer:

class VerifyUserSerializer(serializers.ModelSerializer):

    # ----------------------------------------
    # Meta, create, update
    # ----------------------------------------
    class Meta:
        model = UserProfile
        fields = ["verification_token"]

    # ----------------------------------------
    # Custom Validation
    # ----------------------------------------
    def validate_verification_token(self, token):
        """Makes the token required and compare its value to the database"""
        # Check empty
        message = gettext("'verification_token' is required")
        token = is_empty(token, message)
        # Find matching user
        user = try_get_object(UserProfile, verification_token=token)
        if not user:
            message = gettext("Invalid Verification Token")
            raise serializers.ValidationError(message)
        # Return unchanged
        return token

Viewset:

class VerifyUserViewset(viewsets.GenericViewSet):
    # ----------------------------------------
    # Settings
    # ----------------------------------------
    permission_classes = (permissions.AllowAny, )
    serializer_class = VerifyUserSerializer

    # ----------------------------------------
    # Actions
    # ----------------------------------------
    def create(self, request, *args, **kwargs):
        """POST: Verify the user using its token"""
        # Form validation
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # Validate the user
        token = serializer.validated_data["verification_token"]
        user = UserProfile.objects.get(verification_token=token)
        user.validation_email_verification()
        return Response(None, status=status.HTTP_202_ACCEPTED)


Solution 1:[1]

I've found the solution in the Django Rest Framework API Guide: https://www.django-rest-framework.org/api-guide/routers/#routing-for-extra-actions

Since I have a "users/" endpoint and want to user a "users/verify/" endpoint, I must add an action to my UserViewset (the one bound to "users/") that points to /verify/.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jordan Kowal