Crazy Frog
Crazy Frog

Reputation: 525

Getting message part of serialized._errors when defining a unique constraint for REST

Based on this post, I put a uniqueness constraint on my serializer like this:

class UserSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(validators=[
        UniqueValidator(
            queryset = User.objects.all(),
            message=_('Such email is already registered in the system'),
        )]
    )
    class Meta:
        model = User
        fields = ('username', 'password', 'email', )

And in the views.py, I have:

def create_user(request):
    serialized = UserSerializer(data=request.data)
    if serialized.is_valid():
        #....
    else:
       return Response({'success': False,
                        'detail': serialized._errors,
                        'object': None},
                        status=status.HTTP_400_BAD_REQUEST)

Now, the problem is that through my entire API, I use a standardized structure of json response, and in the detail part, third-party developers always expect a string with error message. However, serialized._errors returns dict: {'email': [u'Such email is already registered in the system']}, and the issue lies in that I need pure string with error message. I know I could use serialized._errors['email'][0], but the question is, does python/Django provide any magic generic syntax which I could use instead of serialized._errors to extract the string message irrespective of the unique field name ? Or maybe I should change the structure of constraint definition somehow to achieve this?

return Response({'success': False,
                 'detail': MAGIC_OPERATOR,
                 'object': None},
                 status=status.HTTP_400_BAD_REQUEST)

Upvotes: 2

Views: 261

Answers (1)

Edgar Navasardyan
Edgar Navasardyan

Reputation: 4511

I suggest you just write a default view which would parse your serialized._errors object and return a custom JSON:

def default_error_response(serialized):
    # Display only the first error and exit the function
    # Edit this logic, if one day you decide to concat all error messages    
    # into one string
    for key in serialized._errors:
        return Response({'success': False,
                         'detail': "%s" % (serialized._errors[key][0]),
                         'error_code': None,
                         'object': None}, status=status.HTTP_400_BAD_REQUEST)

And then in your REST view:

if serialized.is_valid():
  #...
else:
  return default_error_response(serialized)

Upvotes: 1

Related Questions