Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 955
jimbo Avatar asked Sep 29 '17 16:09

jimbo


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
like image 195
Johannes Reichard Avatar answered Oct 02 '22 22:10

Johannes Reichard