I have a queryset like:
qs = MyModel.objects.filter(name=\'me\').values_list(\'activation_date\')
here activation_date is
extra
is deprecated in Django 2.0
That's why I think the best solution to get a stringified datetime is:
foo_bar = FooBarModel.objects.annotate(
str_datetime=Cast(
TruncSecond('some_datetime_field', DateTimeField()), CharField()
)
).values('str_datetime').first()
The result is:
foo_bar.str_datetime:
(str)'2014-03-28 15:36:55'
Also I'd like to mention that you can format it as well in any way you want like:
from django.db.models import Value
foo_bar = FooBarModel.objects.annotate(
day=Cast(ExtractDay('some_datetime_field'), CharField()),
hour=Cast(ExtractHour('some_datetime_field'), CharField()),
str_datetime=Concat(
Value('Days: '), 'day', Value(' Hours: '), 'hour',
output_field=CharField()
)
).values('str_datetime').first()
The result is:
foo_bar.str_datetime:
(str)'Days: 28 Hours: 15'
Very surprised to see that no one suggested the cast to a simple TextField
(note, I'm using Postgres so I can't confirm for other RDBMSes):
queryset = FooBarModel.objects.values(my_datetime=Cast('some_datetime_field', TextField()))
foo_bar = queryset.first()
foo_bar['my_datetime']
>>> u'2019-10-03 17:59:37.979578+00'
It similarly also works fine for nested fields:
queryset = FooBarModel.objects.values(Cast('baz__some_datetime_field', TextField()))
Alternatively, a custom Func
can also be used (also specific to Postgres here, but can be modified for any other RDBMS):
class FullDateTimeCast(Func):
"""
Coerce an expression to a new field type.
"""
function = 'TO_CHAR'
template = '%(function)s(%(expressions)s, \'FMDay, Month DD, YYYY at HH12:MI:SS AM\')'
queryset = FooBarModel.objects.values(my_datetime=FullDateTimeCast('some_datetime_field', TextField()))
foo_bar = queryset.first()
foo_bar['my_datetime']
>>> u' Thursday, October 03, 2019 at 17:59:37 PM'