Customize Status code response from Django Rest Framework serializer

Multi tool use
Multi tool use









0















The scenario is quite straight-forward:



Say i have a user model where email should be unique. I did a custom validation for this like.



def validate_email(self, value):
if value is not None:
exist_email = User.objects.filter(email=value).first()
if exist_email:
raise serializers.ValidationError("This Email is already taken")
return value


from rest_framework response when input validation occur we should return status_code_400 for BAD_REQUEST but in this scenario we should or we need to return status_code_409 for conflicting entry. What is the best way to customize status_code response from serializer_errors validation.










share|improve this question


























    0















    The scenario is quite straight-forward:



    Say i have a user model where email should be unique. I did a custom validation for this like.



    def validate_email(self, value):
    if value is not None:
    exist_email = User.objects.filter(email=value).first()
    if exist_email:
    raise serializers.ValidationError("This Email is already taken")
    return value


    from rest_framework response when input validation occur we should return status_code_400 for BAD_REQUEST but in this scenario we should or we need to return status_code_409 for conflicting entry. What is the best way to customize status_code response from serializer_errors validation.










    share|improve this question
























      0












      0








      0








      The scenario is quite straight-forward:



      Say i have a user model where email should be unique. I did a custom validation for this like.



      def validate_email(self, value):
      if value is not None:
      exist_email = User.objects.filter(email=value).first()
      if exist_email:
      raise serializers.ValidationError("This Email is already taken")
      return value


      from rest_framework response when input validation occur we should return status_code_400 for BAD_REQUEST but in this scenario we should or we need to return status_code_409 for conflicting entry. What is the best way to customize status_code response from serializer_errors validation.










      share|improve this question














      The scenario is quite straight-forward:



      Say i have a user model where email should be unique. I did a custom validation for this like.



      def validate_email(self, value):
      if value is not None:
      exist_email = User.objects.filter(email=value).first()
      if exist_email:
      raise serializers.ValidationError("This Email is already taken")
      return value


      from rest_framework response when input validation occur we should return status_code_400 for BAD_REQUEST but in this scenario we should or we need to return status_code_409 for conflicting entry. What is the best way to customize status_code response from serializer_errors validation.







      django serializer






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 28 '18 at 12:32









      ShakilShakil

      5281315




      5281315






















          3 Answers
          3






          active

          oldest

          votes


















          0














          I would go for intercepting ValidationError exception and return the Response object with 409 status code:



          try:
          serializer.is_valid(raise_exception=True)
          except ValidationError, msg:
          if str(msg) == "This Email is already taken":
          return Response(
          'ValidationError': str(msg),
          status=status.HTTP_409_CONFLICT
          )
          return Response(
          'ValidationError': str(msg),
          status=status.HTTP_400_BAD_REQUEST
          )





          share|improve this answer
































            0














            I think is better to define custom exception_handler like:



            settings.py



            REST_FRAMEWORK = 
            'EXCEPTION_HANDLER': 'myproject.common.custom_classes.handler.exception_handler',



            handler.py



            def exception_handler(exc, context):
            # Custom exception hanfling
            if isinstance(exc, UniqueEmailException):
            set_rollback()
            data = 'detail': exc.detail
            return Response(data, status=exc.status_code)

            elif isinstance(exc, (exceptions.APIException, ValidationError)):
            headers =
            if getattr(exc, 'auth_header', None):
            headers['WWW-Authenticate'] = exc.auth_header
            if getattr(exc, 'wait', None):
            headers['Retry-After'] = '%d' % exc.wait

            if hasattr(exc, 'error_dict') and isinstance(exc, ValidationError):
            exc.status_code = HTTP_400_BAD_REQUEST
            data = exc.message_dict
            elif isinstance(exc.detail, (list, dict)):
            data = exc.detail
            else:
            data = 'detail': exc.detail

            set_rollback()
            return Response(data, status=exc.status_code, headers=headers)

            elif isinstance(exc, Http404):
            msg = _('Not found.')
            data = 'detail': six.text_type(msg)

            set_rollback()
            return Response(data, status=status.HTTP_404_NOT_FOUND)

            return None


            exceptions.py



            class UniqueEmailException(APIException):
            status_code = status.HTTP_409_CONFLICT
            default_detail = 'Error Message'


            And finally the validator:



            def validate_email(self, value):
            if value is not None:
            exist_email = User.objects.filter(email=value).first()
            if exist_email:
            raise UniqueEmailException()
            return value





            share|improve this answer






























              0














              Short answer:



              You can't return custom response codes from a serializer.



              This is because the serializer is just that: A Serializer. It doesn't, or shouldn't, deal with HTTP at all. It's just for formatting data, usually as JSON, but it'll usually do HTML for showing your API, and one or two other formats.



              Long answer:



              One way to accomplish this is to raise something (doesn't matter what, but make it descriptive) in your serializer, and add code to your view to catch the error. Your view can return a custom response code with a custom response body as you like it.



              Like this:



              add something like this to your view class:



              def create(self, request, *args, **kwargs):
              try:
              return super().create(request, *args, **kwargs)
              except ValidationError as x:
              return Response(x.args, status=status.HTTP_409_CONFLICT)





              share|improve this answer






















                Your Answer






                StackExchange.ifUsing("editor", function ()
                StackExchange.using("externalEditor", function ()
                StackExchange.using("snippets", function ()
                StackExchange.snippets.init();
                );
                );
                , "code-snippets");

                StackExchange.ready(function()
                var channelOptions =
                tags: "".split(" "),
                id: "1"
                ;
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function()
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled)
                StackExchange.using("snippets", function()
                createEditor();
                );

                else
                createEditor();

                );

                function createEditor()
                StackExchange.prepareEditor(
                heartbeatType: 'answer',
                autoActivateHeartbeat: false,
                convertImagesToLinks: true,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: 10,
                bindNavPrevention: true,
                postfix: "",
                imageUploader:
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                ,
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                );



                );













                draft saved

                draft discarded


















                StackExchange.ready(
                function ()
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f48486390%2fcustomize-status-code-response-from-django-rest-framework-serializer%23new-answer', 'question_page');

                );

                Post as a guest















                Required, but never shown

























                3 Answers
                3






                active

                oldest

                votes








                3 Answers
                3






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                0














                I would go for intercepting ValidationError exception and return the Response object with 409 status code:



                try:
                serializer.is_valid(raise_exception=True)
                except ValidationError, msg:
                if str(msg) == "This Email is already taken":
                return Response(
                'ValidationError': str(msg),
                status=status.HTTP_409_CONFLICT
                )
                return Response(
                'ValidationError': str(msg),
                status=status.HTTP_400_BAD_REQUEST
                )





                share|improve this answer





























                  0














                  I would go for intercepting ValidationError exception and return the Response object with 409 status code:



                  try:
                  serializer.is_valid(raise_exception=True)
                  except ValidationError, msg:
                  if str(msg) == "This Email is already taken":
                  return Response(
                  'ValidationError': str(msg),
                  status=status.HTTP_409_CONFLICT
                  )
                  return Response(
                  'ValidationError': str(msg),
                  status=status.HTTP_400_BAD_REQUEST
                  )





                  share|improve this answer



























                    0












                    0








                    0







                    I would go for intercepting ValidationError exception and return the Response object with 409 status code:



                    try:
                    serializer.is_valid(raise_exception=True)
                    except ValidationError, msg:
                    if str(msg) == "This Email is already taken":
                    return Response(
                    'ValidationError': str(msg),
                    status=status.HTTP_409_CONFLICT
                    )
                    return Response(
                    'ValidationError': str(msg),
                    status=status.HTTP_400_BAD_REQUEST
                    )





                    share|improve this answer















                    I would go for intercepting ValidationError exception and return the Response object with 409 status code:



                    try:
                    serializer.is_valid(raise_exception=True)
                    except ValidationError, msg:
                    if str(msg) == "This Email is already taken":
                    return Response(
                    'ValidationError': str(msg),
                    status=status.HTTP_409_CONFLICT
                    )
                    return Response(
                    'ValidationError': str(msg),
                    status=status.HTTP_400_BAD_REQUEST
                    )






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jan 28 '18 at 14:29

























                    answered Jan 28 '18 at 14:12









                    roberturobertu

                    3615




                    3615























                        0














                        I think is better to define custom exception_handler like:



                        settings.py



                        REST_FRAMEWORK = 
                        'EXCEPTION_HANDLER': 'myproject.common.custom_classes.handler.exception_handler',



                        handler.py



                        def exception_handler(exc, context):
                        # Custom exception hanfling
                        if isinstance(exc, UniqueEmailException):
                        set_rollback()
                        data = 'detail': exc.detail
                        return Response(data, status=exc.status_code)

                        elif isinstance(exc, (exceptions.APIException, ValidationError)):
                        headers =
                        if getattr(exc, 'auth_header', None):
                        headers['WWW-Authenticate'] = exc.auth_header
                        if getattr(exc, 'wait', None):
                        headers['Retry-After'] = '%d' % exc.wait

                        if hasattr(exc, 'error_dict') and isinstance(exc, ValidationError):
                        exc.status_code = HTTP_400_BAD_REQUEST
                        data = exc.message_dict
                        elif isinstance(exc.detail, (list, dict)):
                        data = exc.detail
                        else:
                        data = 'detail': exc.detail

                        set_rollback()
                        return Response(data, status=exc.status_code, headers=headers)

                        elif isinstance(exc, Http404):
                        msg = _('Not found.')
                        data = 'detail': six.text_type(msg)

                        set_rollback()
                        return Response(data, status=status.HTTP_404_NOT_FOUND)

                        return None


                        exceptions.py



                        class UniqueEmailException(APIException):
                        status_code = status.HTTP_409_CONFLICT
                        default_detail = 'Error Message'


                        And finally the validator:



                        def validate_email(self, value):
                        if value is not None:
                        exist_email = User.objects.filter(email=value).first()
                        if exist_email:
                        raise UniqueEmailException()
                        return value





                        share|improve this answer



























                          0














                          I think is better to define custom exception_handler like:



                          settings.py



                          REST_FRAMEWORK = 
                          'EXCEPTION_HANDLER': 'myproject.common.custom_classes.handler.exception_handler',



                          handler.py



                          def exception_handler(exc, context):
                          # Custom exception hanfling
                          if isinstance(exc, UniqueEmailException):
                          set_rollback()
                          data = 'detail': exc.detail
                          return Response(data, status=exc.status_code)

                          elif isinstance(exc, (exceptions.APIException, ValidationError)):
                          headers =
                          if getattr(exc, 'auth_header', None):
                          headers['WWW-Authenticate'] = exc.auth_header
                          if getattr(exc, 'wait', None):
                          headers['Retry-After'] = '%d' % exc.wait

                          if hasattr(exc, 'error_dict') and isinstance(exc, ValidationError):
                          exc.status_code = HTTP_400_BAD_REQUEST
                          data = exc.message_dict
                          elif isinstance(exc.detail, (list, dict)):
                          data = exc.detail
                          else:
                          data = 'detail': exc.detail

                          set_rollback()
                          return Response(data, status=exc.status_code, headers=headers)

                          elif isinstance(exc, Http404):
                          msg = _('Not found.')
                          data = 'detail': six.text_type(msg)

                          set_rollback()
                          return Response(data, status=status.HTTP_404_NOT_FOUND)

                          return None


                          exceptions.py



                          class UniqueEmailException(APIException):
                          status_code = status.HTTP_409_CONFLICT
                          default_detail = 'Error Message'


                          And finally the validator:



                          def validate_email(self, value):
                          if value is not None:
                          exist_email = User.objects.filter(email=value).first()
                          if exist_email:
                          raise UniqueEmailException()
                          return value





                          share|improve this answer

























                            0












                            0








                            0







                            I think is better to define custom exception_handler like:



                            settings.py



                            REST_FRAMEWORK = 
                            'EXCEPTION_HANDLER': 'myproject.common.custom_classes.handler.exception_handler',



                            handler.py



                            def exception_handler(exc, context):
                            # Custom exception hanfling
                            if isinstance(exc, UniqueEmailException):
                            set_rollback()
                            data = 'detail': exc.detail
                            return Response(data, status=exc.status_code)

                            elif isinstance(exc, (exceptions.APIException, ValidationError)):
                            headers =
                            if getattr(exc, 'auth_header', None):
                            headers['WWW-Authenticate'] = exc.auth_header
                            if getattr(exc, 'wait', None):
                            headers['Retry-After'] = '%d' % exc.wait

                            if hasattr(exc, 'error_dict') and isinstance(exc, ValidationError):
                            exc.status_code = HTTP_400_BAD_REQUEST
                            data = exc.message_dict
                            elif isinstance(exc.detail, (list, dict)):
                            data = exc.detail
                            else:
                            data = 'detail': exc.detail

                            set_rollback()
                            return Response(data, status=exc.status_code, headers=headers)

                            elif isinstance(exc, Http404):
                            msg = _('Not found.')
                            data = 'detail': six.text_type(msg)

                            set_rollback()
                            return Response(data, status=status.HTTP_404_NOT_FOUND)

                            return None


                            exceptions.py



                            class UniqueEmailException(APIException):
                            status_code = status.HTTP_409_CONFLICT
                            default_detail = 'Error Message'


                            And finally the validator:



                            def validate_email(self, value):
                            if value is not None:
                            exist_email = User.objects.filter(email=value).first()
                            if exist_email:
                            raise UniqueEmailException()
                            return value





                            share|improve this answer













                            I think is better to define custom exception_handler like:



                            settings.py



                            REST_FRAMEWORK = 
                            'EXCEPTION_HANDLER': 'myproject.common.custom_classes.handler.exception_handler',



                            handler.py



                            def exception_handler(exc, context):
                            # Custom exception hanfling
                            if isinstance(exc, UniqueEmailException):
                            set_rollback()
                            data = 'detail': exc.detail
                            return Response(data, status=exc.status_code)

                            elif isinstance(exc, (exceptions.APIException, ValidationError)):
                            headers =
                            if getattr(exc, 'auth_header', None):
                            headers['WWW-Authenticate'] = exc.auth_header
                            if getattr(exc, 'wait', None):
                            headers['Retry-After'] = '%d' % exc.wait

                            if hasattr(exc, 'error_dict') and isinstance(exc, ValidationError):
                            exc.status_code = HTTP_400_BAD_REQUEST
                            data = exc.message_dict
                            elif isinstance(exc.detail, (list, dict)):
                            data = exc.detail
                            else:
                            data = 'detail': exc.detail

                            set_rollback()
                            return Response(data, status=exc.status_code, headers=headers)

                            elif isinstance(exc, Http404):
                            msg = _('Not found.')
                            data = 'detail': six.text_type(msg)

                            set_rollback()
                            return Response(data, status=status.HTTP_404_NOT_FOUND)

                            return None


                            exceptions.py



                            class UniqueEmailException(APIException):
                            status_code = status.HTTP_409_CONFLICT
                            default_detail = 'Error Message'


                            And finally the validator:



                            def validate_email(self, value):
                            if value is not None:
                            exist_email = User.objects.filter(email=value).first()
                            if exist_email:
                            raise UniqueEmailException()
                            return value






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Jan 29 '18 at 16:29









                            MauMau

                            665




                            665





















                                0














                                Short answer:



                                You can't return custom response codes from a serializer.



                                This is because the serializer is just that: A Serializer. It doesn't, or shouldn't, deal with HTTP at all. It's just for formatting data, usually as JSON, but it'll usually do HTML for showing your API, and one or two other formats.



                                Long answer:



                                One way to accomplish this is to raise something (doesn't matter what, but make it descriptive) in your serializer, and add code to your view to catch the error. Your view can return a custom response code with a custom response body as you like it.



                                Like this:



                                add something like this to your view class:



                                def create(self, request, *args, **kwargs):
                                try:
                                return super().create(request, *args, **kwargs)
                                except ValidationError as x:
                                return Response(x.args, status=status.HTTP_409_CONFLICT)





                                share|improve this answer



























                                  0














                                  Short answer:



                                  You can't return custom response codes from a serializer.



                                  This is because the serializer is just that: A Serializer. It doesn't, or shouldn't, deal with HTTP at all. It's just for formatting data, usually as JSON, but it'll usually do HTML for showing your API, and one or two other formats.



                                  Long answer:



                                  One way to accomplish this is to raise something (doesn't matter what, but make it descriptive) in your serializer, and add code to your view to catch the error. Your view can return a custom response code with a custom response body as you like it.



                                  Like this:



                                  add something like this to your view class:



                                  def create(self, request, *args, **kwargs):
                                  try:
                                  return super().create(request, *args, **kwargs)
                                  except ValidationError as x:
                                  return Response(x.args, status=status.HTTP_409_CONFLICT)





                                  share|improve this answer

























                                    0












                                    0








                                    0







                                    Short answer:



                                    You can't return custom response codes from a serializer.



                                    This is because the serializer is just that: A Serializer. It doesn't, or shouldn't, deal with HTTP at all. It's just for formatting data, usually as JSON, but it'll usually do HTML for showing your API, and one or two other formats.



                                    Long answer:



                                    One way to accomplish this is to raise something (doesn't matter what, but make it descriptive) in your serializer, and add code to your view to catch the error. Your view can return a custom response code with a custom response body as you like it.



                                    Like this:



                                    add something like this to your view class:



                                    def create(self, request, *args, **kwargs):
                                    try:
                                    return super().create(request, *args, **kwargs)
                                    except ValidationError as x:
                                    return Response(x.args, status=status.HTTP_409_CONFLICT)





                                    share|improve this answer













                                    Short answer:



                                    You can't return custom response codes from a serializer.



                                    This is because the serializer is just that: A Serializer. It doesn't, or shouldn't, deal with HTTP at all. It's just for formatting data, usually as JSON, but it'll usually do HTML for showing your API, and one or two other formats.



                                    Long answer:



                                    One way to accomplish this is to raise something (doesn't matter what, but make it descriptive) in your serializer, and add code to your view to catch the error. Your view can return a custom response code with a custom response body as you like it.



                                    Like this:



                                    add something like this to your view class:



                                    def create(self, request, *args, **kwargs):
                                    try:
                                    return super().create(request, *args, **kwargs)
                                    except ValidationError as x:
                                    return Response(x.args, status=status.HTTP_409_CONFLICT)






                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Nov 12 '18 at 21:11









                                    John GilmoreJohn Gilmore

                                    104




                                    104



























                                        draft saved

                                        draft discarded
















































                                        Thanks for contributing an answer to Stack Overflow!


                                        • Please be sure to answer the question. Provide details and share your research!

                                        But avoid


                                        • Asking for help, clarification, or responding to other answers.

                                        • Making statements based on opinion; back them up with references or personal experience.

                                        To learn more, see our tips on writing great answers.




                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function ()
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f48486390%2fcustomize-status-code-response-from-django-rest-framework-serializer%23new-answer', 'question_page');

                                        );

                                        Post as a guest















                                        Required, but never shown





















































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown

































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown







                                        6xOYUC AxT6MKRDyVoe83pXfgerfmuqLvgrIA4a0yla
                                        wFROkAgSJ5Iqhbpt4NVIKR1JCWrA9Gg2 sHykX4Nl1DmGX,mEfLzEb0,i,9pxz7

                                        Popular posts from this blog

                                        Use pre created SQLite database for Android project in kotlin

                                        Ruanda

                                        Ondo