DRF - How to handle exception on serializer create()?

Viewed 16111

I'm using the friendship Django module with Django Rest Framework. When creating an API the Serializer's create() may raise some exceptions - AlreadyFriendsError, DoesNotExist or AssertionError. Now when an exception occurs, the return object is not valid (None) and I get a Traceback with the AssertionError: create() did not return an object instance.

From my API views.py

class FriendManageAPIView(CreateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = FriendManageSerializer

    def post(self, request, *args, **kwargs):
        if request.data['action'] == 'add_friend':
            return self.create(request, *args, **kwargs)

From my API serializers.py

class FriendManageSerializer(serializers.ModelSerializer):
    to_user = serializers.CharField(max_length=150)

    def create(self, validated_data):
        friendship_ret = None
        try:
            request = self.context.get("request")
            if request and hasattr(request, "user"):
                user = request.user

            user_model = get_user_model()
            to_user = user_model.objects.get(username=request.data['to_user'])
            friendship_ret = Friend.objects.create(
                from_user=user,  # The sender
                to_user=to_user,  # The recipient
            )
            friendship_ret.save()
        except (AlreadyFriendsError, user_model.DoesNotExist, AssertionError):
            print("EXCEPTION FriendManageSerializer.create()")

        return friendship_ret

How should I really handle this case? What should I be returning when the object is not valid?

1 Answers

I would probably choose a Validation error if you don't want to establish custom errors (here DRF errors http://www.django-rest-framework.org/api-guide/exceptions/).

Your error tells you you need to respond with kind of object because if your try fails None is returned.

except (AlreadyFriendsError, user_model.DoesNotExist, AssertionError):
    raise serializers.ValidationError("human readable error message here")

This should fix your requirement.

Some additional tips for your code:

  1. checkout validation and custom DRF validators http://www.django-rest-framework.org/api-guide/validators/. They can help you in similar situations and help to separate your business logic from your serializers
  2. the except hits 3 different Exceptions. To have an easier to use API you should respond with separate error messages to have more context for the client
Related