django-rest-frameworkresponsebuilt-invalidationerror

How to remove third brackets '[]' from django built in unique field validation erro response


Here is my model

In this CustomerAdd table, I've designed customer_phone with Django builtins unique=True. And for these unique fields, Django raised validation error following: { "customer_phone": [ "This customer_phone has already been registered." ] } How to remove third brackets from built-in validation error! Please help me.

class CustomerAdd(models.Model):
    user = models.ForeignKey('accounts.CustomUser', on_delete=models.CASCADE)
    is_customer = models.BooleanField('customer status', default=True)
    is_supplier = models.BooleanField('supplier status', default=False)
    customer_name = models.CharField(max_length=100)
    customer_phone = models.CharField(max_length=15, unique=True, error_messages={'unique': "This customer_phone has "
                                                                                            "already been registered."})
    previous_due = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    date = models.DateField(auto_now_add=True)
    picture = models.ImageField(upload_to='customer_add_pics', default='images.png')

    def __str__(self):
        return self.customer_name

    class Meta:
        verbose_name = "Customer Add"
        verbose_name_plural = "Customer Add"

And here is API Response:

{
    "customer_phone": [
        "This customer_phone has already been registered."
    ]
}

Solution

  • Django raised validation error following: { "customer_phone": [ "This customer_phone has already been registered." ] }

    The reason this happens is because the same field can have multiple errors. For example a password field can require that it contains at least eight characters, and that it contains at least one digit. By using a list, it thus is capable to list one or more problems with the same field. From a modeling point-of-view, this is thus a more sensical way to report errors.

    You can implement custom exception handling [drf-doc] to only use the first item for each field with:

    # app_name/utils.py
    
    from rest_framework.views import exception_handler
    from rest_framework.exceptions import ValidationError
    
    def custom_exception_handler(exc, context):
        if isinstance(exc, ValidationError) and isinstance(exc.detail, dict):
            data = {
                k: vs[0]
                for k, vs in exc.detail.items()
            }
            exc = ValidationError(detail=data)
        
        return exception_handler(exc, context)

    and then set the exception handler to:

    # settings.py
    
    REST_FRAMEWORK = {
        # …,
        'EXCEPTION_HANDLER': 'app_name.utils.custom_exception_handler'
    }

    But I think this is not a good idea. A single field can simply have multiple problems and thus raise multiple validation errors.