Search code examples
django-rest-frameworkpython-3.6datefield

Error about DateField format in serializer


I have a serializer and I can't manage to validate the data due to a validation error about the date format, although I am sure the date format is correct. I would like to keep the field as optional, but I can't make it work when I pass the date value. When I don't pass any value, the serializer works correctly.

Example:

from rest_framework.serializers import serializers
class SerializerX(serializers.Serializer):
    date_x = serializers.DateField(required=False, allow_null=True, format="%Y-%m-%d", input_formats=["%Y-%m-%d"])

s = SerializerX(data={'date_x': '2022-02-16'})
s.is_valid()
s.initial_data = {'date_x': '2022-02-16T00:00:00'} (before calling is_valid())
s.validated_data = {}
s.data = {'date_x': '2022-02-16T00:00:00'}

In my local environment, the serializer works correctly, but in a remote development environment (Kubernetes pod), the following error happens:

Validation error: 
{'date_x': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY-MM-DD.', code='invalid')]}

Note: There are no differences in settings between the environments.

I have tried:

  1. Adding DATE_FORMAT = "%Y-%m-%d" and DATE_INPUT_FORMATS = ['%Y-%m-%d', ] to settings and removing the format and input_formats from the field definition.
  2. Adding DATE_FORMAT = "%Y-%m-%d" and DATE_INPUT_FORMATS = ['%Y-%m-%d', ] to REST_FRAMEWORK settings and removing the format and input_formats from the field definition.
  3. Overriding validation_methods like validate() and validate_date_x()
  4. Disable USE_L10N
  5. Defining custom DateField class like this:
from django.utils import formats
class DateFieldX(serializers.DateField):
    def to_representation(self, obj):
          return formats.date_format(obj, 'Y-m-d')

About the environment:

Django 2.1.7
djangorestframework 3.9.2
Python 3.6.14

Current relevant settings:

TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True

I would appreciate any kind of help. Thanks in advance


Solution

  • I have found the following solution, whose key aspects are:

    • To define the field as DateTimeField instead of DateField
    • To ensure the input format is always a string
    • To override the validation method to ensure DRF manages always the value as string.
    from rest_framework.serializers import serializers
    class SerializerX(serializers.Serializer):
        date_x = serializers.DateTimeField(
            required=False, allow_null=True,
            format="%Y-%m-%d", 
            input_formats=["%Y-%m-%dT%H:%M:%S", "%Y-%m-%d"]
        )
    
        def validate(self, value):
            return value.strftime('%Y-%m-%d') if value else value