Search code examples
python-3.xdjangodjango-rest-frameworkdjango-serializerrequired

How do I get Django rest framework to respect the "required=false" designation in my serializer?


I'm using djangorestframework==3.12.2 . I have this Serializer. Some fields, like "desc_english" I don't want to be required ...

class ValidateNewCoopSerializer(serializers.Serializer):
    coop_name=serializers.CharField()
    street=serializers.CharField()
    address_public=serializers.CharField()
    city=serializers.CharField()
    state=serializers.CharField()
    zip=serializers.CharField()
    county=serializers.CharField()
    country=serializers.CharField()
    websites=serializers.CharField()
    contact_name=serializers.CharField()
    contact_name_public=serializers.CharField()
    contact_email=serializers.CharField()
    contact_email_public=serializers.CharField()
    contact_phone=serializers.CharField()
    contact_phone_public=serializers.CharField()
    scope=serializers.CharField()
    tags=serializers.CharField(required=False)
    desc_english=serializers.CharField(required=False)
    desc_other=serializers.CharField(required=False)
    req_reason=serializers.CharField()

which is used in my views.py file like so

@api_view(('POST',))
def save_to_sheet_from_form(request):
    """
    This is supposed to write to a Google sheet given a form coming from
    the client.
    """
    valid_ser = ValidateNewCoopSerializer(data=request.data)
    if valid_ser.is_valid():
        post_data = valid_ser.validated_data
        ...
        return Response(post_data, status=status.HTTP_201_CREATED)
    else:
        return Response(valid_ser.errors, status=status.HTTP_400_BAD_REQUEST)

I notice, though, that when I submit requests, the fields are mark as not required are coming back with errors ...

curl 'http://localhost:8000/save_to_sheet_from_form/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0' -H 'Accept: */*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Referer: http://localhost:3001/' -H 'Content-Type: application/json' -H 'Origin: http://localhost:3001' -H 'Connection: keep-alive' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' --data-raw '{"coop_name":"","street":"","address_public":"no","city":"","state":"IL","zip":"","county":"","country":"US","websites":"","contact_name":"","contact_name_public":"no","contact_email":"","contact_email_public":"no","contact_phone":"","contact_phone_public":"no","scope":"local","tags":"","desc_english":"","desc_other":"","req_reason":"add"}'

results in

{"coop_name":["This field may not be blank."],"street":["This field may not be blank."],"city":["This field may not be blank."],"zip":["This field may not be blank."],"county":["This field may not be blank."],"websites":["This field may not be blank."],"contact_name":["This field may not be blank."],"contact_email":["This field may not be blank."],"contact_phone":["This field may not be blank."],"tags":["This field may not be blank."],"desc_english":["This field may not be blank."],"desc_other":["This field may not be blank."]}

How do I configure my serializer so that these fields are actually not required?


Solution

  • You have set required=False on the serializer fields. This means that if you don't supply the key for them in the request it will work, but if you do supply the key then they would be validated. Looking at your request you pass "desc_english":"", i.e. you do supply the key with an empty string, hence that error is correct. You can set allow_blank=True [DRF docs] on the field if you want to allow empty strings:

    desc_english=serializers.CharField(required=False, allow_blank=True)
    

    If you may want to pass null values (None in python) to the field you can also set allow_null [DRF docs] to True:

    desc_english=serializers.CharField(required=False, allow_blank=True, allow_null=True)