Manuel Carrero
Manuel Carrero

Reputation: 637

Error: too many values to unpack (expected 2) when raise error with serializers.ValidationError

I'm trying to validate empty fields in an endpoint by overwriting to_internal_value function and displaying an error message with ValidationError, very similar as the following answer:

serializer.py

def to_internal_value(self, data):
    missing = []
    for k in ['comments']:
        try:
            if data[k] == '':
                missing.append(k)
        except Exception as e:
            missing.append(k)
        if len(missing):
            raise serializers.ValidationError("The following fields are required: %s" % ','.join(missing))
    return data

The problem is that I get: Error: too many values to unpack (expected 2) when raise serializers.ValidationError instruction is executed and data is comming with comments field empty (''):

(Pdb) data
<QueryDict: {'csrfmiddlewaretoken': ['<csrfmiddlewaretoken>'], 'comments': [''], 'user': ['']}>

Even testing with a simple string:

raise serializers.ValidationError("The following fields are required: comments")

I receive the same error. In the python console, raise throw the error:

>>> from rest_framework.serializers import ValidationError
>>> from rest_framework import serializers
>>> data={'comments': [''], 'user': ['']}
>>> missing=[]
>>> missing.append('comments')
>>> raise serializers.ValidationError("The following fields are required: %s" % ','.join(missing))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
rest_framework.exceptions.ValidationError: [ErrorDetail(string='The following fields are required: comments', code='invalid')]

Instead of serializers.ValidationError() I had to use ValueError() and It works good, but I guess that it's not the suggested way.

Edit I was using:

Django==2.2.4
djangorestframework==3.10.3

Then I upgraded to:

Django==2.2.9
djangorestframework==3.11.0

With the same results.

Upvotes: 7

Views: 2817

Answers (2)

VsM
VsM

Reputation: 51

The reason is that ValidationError raised inside run_validation should be created with dict, for example:

ValidationError(','.join(missing): "These field are required")

Upvotes: 5

Charlotte Mays
Charlotte Mays

Reputation: 385

The reason this happens is that to_internal_value collects all the validation errors and passes them up as a dictionary, so that the resulting 400 response can include all the errors that were found rather than just the first one it hits. This should work:

def to_internal_value(self, data):
    missing = []
    for k in ['comments']:
        try:
            if data[k] == '':
                missing.append(k)
        except Exception as e:
            missing.append(k)
        if len(missing):
            raise serializers.ValidationError(
                {"The following fields are required": missing}
            )
    return data

That said, if all you're doing is validating that something is present, I'd suggest declaring required=True on the field in your serializer instead, and then DRF will do this check for you.

Upvotes: 7

Related Questions