Reputation:
at my Django application (DRF only), I'm trying to create a new object where one of the fields is setup like this:
resource_name = models.CharField(verbose_name="Resource Name", blank=False, null=False, max_length=50, unique=True)
If I now try to create an Object with the same resource_name twice, I'm always running into the following exception:
django.db.utils.IntegrityError: (1062, "Duplicate entry 'test_ressource123' for key 'resource_name'")
Is there any good solution that I can apply to all kinds of these situations? Would be awesome to simply make the API response that the object already exists, kinda strange that this is not already a built-in of DRF. Can I maybe overwrite the def create function call of the serializer ? Any good advice welcome.
Upvotes: 0
Views: 1472
Reputation: 421
It is better to add UniqueValidator
to your serializer.
resource_name = serializers.CharField(max_length=50, validators=[UniqueValidator(queryset=YourModel.objects.all())], requierd=False)
Upvotes: 3
Reputation: 3860
Generally, you should develop a serializer for each model to understand how you work with each one. Later you can forget about this "common" solution and look for a bug for a long time.
Nevertheless, I see two approaches to achieve that behavior.
ModelViewSet
We can redefine the create
method of default ModelViewSet
and then inherit your ModelViewSet
s from this class. Like this:
from django.db import IntegrityError
from rest_framework import viewsets
from rest_framework.exceptions import APIException
from rest_framework.status import HTTP_400_BAD_REQUEST
class SupressIntegrityErrorModelViewSet(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
try:
return super().create(request, *args, **kwargs)
except IntegrityError as e:
raise APIException(detail=str(e), code=HTTP_400_BAD_REQUEST)
More information here.
Firstly you need to make a custom_exception_handler
method; DRF documentation suggests making it in <application-directory>/utils.py
:
from django.http import HttpResponseBadRequest
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
if type(exc).__name__ == 'IntegrityError':
return HttpResponseBadRequest(str(e))
return exception_handler(exc, context)
Then you have to set EXCEPTION_HANDLER
in your settings.py
:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
Upvotes: 2