Customize Status code response from Django Rest Framework serializer

Multi tool use
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
add a comment |
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
add a comment |
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
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
django serializer
asked Jan 28 '18 at 12:32


ShakilShakil
5281315
5281315
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
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
)
add a comment |
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
add a comment |
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)
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
)
add a comment |
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
)
add a comment |
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
)
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
)
edited Jan 28 '18 at 14:29
answered Jan 28 '18 at 14:12


roberturobertu
3615
3615
add a comment |
add a comment |
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
add a comment |
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
add a comment |
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
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
answered Jan 29 '18 at 16:29
MauMau
665
665
add a comment |
add a comment |
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)
add a comment |
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)
add a comment |
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)
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)
answered Nov 12 '18 at 21:11


John GilmoreJohn Gilmore
104
104
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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