0

Is there a way to make my serializer print the datetimefield by default like this

 2022-03-28T00:00:00+00:00

Instead of this

 2022-03-23T03:16:00Z 

I get the first output when I do this

return obj.time.isoformat()
Abhishek AN
  • 648
  • 7
  • 24

2 Answers2

1

The simplest way to do it is to specify the format you want in your serializer:

class MySerializer(serializer.Serializer):

    my_date = serializers.DateTimeField(format='%Y-%m-%dT%H:%M')  # Specify your format here
ThomasGth
  • 826
  • 7
  • 18
1

Cause

If you look into the code of django-rest-framework in serializers.DateTimeField if datetime is UTC timezone, the UTC offset (+00:00) will get converted to Z as can be seen here

Solution

If you want to make it reusable for DateTimeField, you need to create a custom serializer DateTimeField that inherits from serializers.DateTimeField and override the to_representation method by coping codes from django-rest-framework and removing lines that convert UTC offset string to Z.

from restframework import ISO_8601
from restframework import serializers


class CustomDateTimeField(serializers.DateTimeField):

    def to_representation(self, value):
        if not value:
            return None

        output_format = getattr(self, 'format', api_settings.DATETIME_FORMAT)

        if output_format is None or isinstance(value, str):
            return value

        value = self.enforce_timezone(value)

        if output_format.lower() == ISO_8601:
            value = value.isoformat()
            # remove lines that convert "+00:00" to "Z"
            # See https://github.com/encode/django-rest-framework/blob/f4cf0260bf3c9323e798325702be690ca25949ca/rest_framework/fields.py#L1239:L1240
            return value
        return value.strftime(output_format)

Then use this in your serializer instead of serializers.DateTimeField

class MySerializer(serializers.Serializer):
    datetime = CustomDateTimeField()

Extra

If you want to use it in serializers.ModelSerializer, you need to follow below steps

  1. Create a custom ModelSerializer that inherits from serializers.ModelSerializer and set serializer_field_mapping attribute as follows
class CustomModelSerializer(serializers.ModelSerializer):
    serializer_field_mapping = {
        # copy serializer_field_mapping
        **serializers.ModelSerializer.serializer_field_mapping,
        # override models.DateTimeField to map to CustomDateTimeField
        models.DateTimeField: CustomDateTimeField,
    }
  1. Use CustomModelSerializer instead of serializers.ModelSerializer. E.g.
class LogSerializer(CustomModelSerializer):
    class Meta:
        model = Log
        fields = ["id", "created_at"]
annonymous
  • 741
  • 3
  • 6
  • Got it thank you, I will try this, I knew the cause of it replacing the offset with Z. Didn't find where the code resided, thanks! Also does this Z give me the timezone of the datetime? – Abhishek AN Mar 26 '22 at 07:37
  • In my understanding, the `Z` is a special case only for UTC timezone. – annonymous Mar 26 '22 at 07:53
  • So only the datetime saved with time zone of UTC gets a Z? In my postgres DB, I can find there's a +05:30 in the ended. In my django project I'm using TZ=true and set the TZ to Asia/Kolkata – Abhishek AN Mar 26 '22 at 10:56
  • 1
    I guess my problem's solved now thank you for the detailed answer. – Abhishek AN Mar 26 '22 at 11:12
  • In my understanding, django stores datetime in the database as UTC time without timezone part. When the data got retrieved from the database, it will be converted to the timezone specified in the django setttings. Hence, you see +05:30 in the end. More details can be found [here](https://docs.djangoproject.com/en/4.0/topics/i18n/timezones/) – annonymous Mar 26 '22 at 12:25