user16837137
user16837137

Reputation:

Django rest framwork - how to prevent 1062, "Duplicate entry"

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

Answers (2)

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

Yevhenii Kosmak
Yevhenii Kosmak

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.

Overriden ModelViewSet

We can redefine the create method of default ModelViewSet and then inherit your ModelViewSets 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.

DRF custom exception handling

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

Related Questions