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.

2 answers

  • answered 2022-01-20 00:37 Yevgeniy Kosmak

    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'
    }
    

  • answered 2022-02-25 18:03 Mohammad sadegh borouny

    It is better to add UniqueValidator to your serializer.

    resource_name = serializers.CharField(max_length=50, validators=[UniqueValidator(queryset=YourModel.objects.all())], requierd=False) 
    

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum