Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 817
Manuel Carrero Avatar asked Dec 31 '19 22:12

Manuel Carrero


People also ask

How do I pass extra data to a serializer?

In function based views we can pass extra context to serializer with "context" parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with "self. context". From example, to get "exclude_email_list" we just used code 'exclude_email_list = self.

What is the use of Serializers?

Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.

What does serializer Is_valid do?

it validates your serializer with the condition of respective field specified in your serializer MessageSerializer .


2 Answers

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.

like image 103
Charlotte Mays Avatar answered Sep 18 '22 01:09

Charlotte Mays


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

ValidationError(','.join(missing): "These field are required")
like image 40
VsM Avatar answered Sep 18 '22 01:09

VsM