Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change validation error responses in DRF?

Tags:

I want to change the JSON, which rest_framework or django returns when a validation error occures.

I will use one of my views as example, but I want to change error messages for all of my views. So let say I have this view meant to login users, providing email and password. If these are correct it returns access_token.

If I post only password , it returns error 400:

{"email": ["This field is required."]} 

and if password and email dont match:

{"detail": ["Unable to log in with provided credentials."]} 

what I want would be more like:

{"errors": [{"field": "email", "message": "This field is required."}]}  {"errors": [{"non-field-error": "Unable to log in with provided credentials."}]} 

Now this is my view:

class OurLoginObtainAuthToken(APIView):     permission_classes = (AllowAny,)     serializer_class = serializers.AuthTokenSerializer     model = Token      def post(self, request):         serializer = self.serializer_class(data=request.DATA)         if serializer.is_valid():             #some magic             return Response(token)                    return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST) 

I can access the serializer.errors and alter them, but it looks like only field errors can be accessed that way, how to change also validation errors created in my serializer`s validate method?

This is my serializer (it is the same serializer as rest_framework.authtoken.serializers.AuthTokenSerializer) but edited, so authentication doesnt require username but email:

class AuthTokenSerializer(serializers.Serializer):     email = serializers.CharField()     password = serializers.CharField()      def validate(self, attrs):         email = attrs.get('email')         password = attrs.get('password')         #print email         #print password         if email and password:             user = authenticate(email=email, password=password)              if user:                 if not user.is_active:                     msg = _('User account is disabled.')                     raise ValidationError(msg)                 attrs['user'] = user                 return attrs             else:                 msg = _('Unable to log in with provided credentials.')                 raise ValidationError(msg)         else:             msg = _('Must include "username" and "password"')             raise ValidationError(msg) 

Or maybe there is a completely different approach? I will be really thankfull for any ideas.

like image 742
Matúš Bartko Avatar asked Jan 28 '15 16:01

Matúš Bartko


1 Answers

The easiest way to change the error style through all the view in your application is to always use serializer.is_valid(raise_exception=True), and then implement a custom exception handler that defines how the error response is created.

like image 103
Tom Christie Avatar answered Sep 18 '22 14:09

Tom Christie