Here’s an example of adding date and time validation to a DateTimeField in a serializer in the Django Rest Framework (DRF).
A first pass, using only the default formats of DateTimeField(), would look like the following:
class CustomSearchFieldsSerializer(serializers.Serializer):
start_time = serializers.DateTimeField()
end_time = serializers.DateTimeField()
def validate(self, data):
# extra validation to ensure that the end date is always after the start date if data['start_time'] > data['end_time']:
raise serializers.ValidationError("finish must occur after start")
return data
Sending a request to that endpoint with the following query parameters (note it only has a date, not time):
/api/v1/custom-search/?start_time=2022-11-01&end_time=2022-11-07
Returns the following 400 Bad Request:
{
"start_time": [
"Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]."
],
"end_time": [
"Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]."
]
}
Not exactly what we want… I want this to be flexible and accept date only as a valid option.
Doing some research on the Django Rest Framework (DRF) documentation, I learned that I could customize the accepted formats. The next iteration looks like this:
class CustomSearchFieldsSerializer(serializers.Serializer):
start_time = serializers.DateTimeField(required=False,
input_formats=["%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d"])
end_time = serializers.DateTimeField(required=False,
input_formats=["%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d"])
The valid input formats can be passed as strings in a list. We add a few options, including a date-only format (the last option in the list).
Note: setting the flag “required” to False: this will make this field optional (in this case, the request could have no start and/or end time, which will then require the setting of some default values in the business logic to limit the query).
For the purposes of the task I was working on, I settled on the following formats:
input_formats=["%Y-%m-%d", "iso-8601"]
The first one accepts date only and the second follows the iso-8601 format, which is also the default format when nothing is set – the exact behaviour that we saw in the very first iteration. iso-8601 is an international standard for the representation of date and time formats.
If you found this helpful, please share this article.
The post Django Rest Framework: adding DateTimeField format serializer validation was originally published at flaviabastos.ca