在django queryset.values_list()中将datetime字段转换为字符串

Nav*_*era 24 django django-models python-2.7

我有一个像这样的查询集:

qs = MyModel.objects.filter(name='me').values_list('activation_date')
Run Code Online (Sandbox Code Playgroud)

这里的activation_date是模型中的DateTimeField.当我从这个qs下载excel表时,我没有以字符串格式获得激活日期. 如何在字符串中转换此字段('activation_date')或如何在qs中对其进行类型转换?

Vic*_*lio 20

https://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield

日期和时间,由datetime.datetime实例在Python中表示.

您可以直接获取DateTimeField的字符串表示形式:

str(obj)
# obj = qs[0][0] ? or qs[0][1] ?
Run Code Online (Sandbox Code Playgroud)

你会得到这样的结果(在这个例子中我使用datetime.datetime.now(),因为DateTimeField由datetime.datetime表示是相同的行为):

>>> now = datetime.datetime.now()
>>> str(now)
'2013-06-26 00:14:26.260524'
Run Code Online (Sandbox Code Playgroud)

如果您想要更少的信息或在其他模式下格式化,您可以使用strftime()函数格式化它们.看到:

>>> now.strftime('%Y-%m-%d %H:%M')
'2013-06-26 00:14'
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法直接在文本时间(例如 11 = 十一月)中获得月份? (2认同)

PKK*_*Kid 8

如果您使用Postgres,您可以这样做(此处为日期格式选项).该解决方案依赖于数据库,但在执行查询后,它确实可以通过Python域中的长列表进行循环.

qs = MyModel.objects.filter(name='me')
qs = qs.extra(select={'datestr':"to_char(activation_date, 'YYYY-MM-DD HH24:MI:SS')"})
qs = qs.values_list('datestr')
Run Code Online (Sandbox Code Playgroud)

我确信MySQL有一些与Postgres的to_char相同的功能,但你必须自己找到它,因为我不是MySQL人.


Eug*_*lev 8

extra 在Django 2.0中已弃用

这就是为什么我认为获得字符串化日期时间的最佳解决方案是:

foo_bar = FooBarModel.objects.annotate(
    str_datetime=Cast(
        TruncSecond('some_datetime_field', DateTimeField()), CharField()
    )
).values('str_datetime').first()
Run Code Online (Sandbox Code Playgroud)

结果是:

foo_bar.str_datetime:
(str)'2014-03-28 15:36:55'
Run Code Online (Sandbox Code Playgroud)

另外我想提一下你也可以用你想要的任何方式格式化它:

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()
Run Code Online (Sandbox Code Playgroud)

结果是:

foo_bar.str_datetime:
(str)'Days: 28 Hours: 15'
Run Code Online (Sandbox Code Playgroud)


Dov*_*vmo 6

非常惊讶地发现没有人建议将其转换为简单的TextField(注意,我使用的是 Postgres,所以我无法确认其他 RDBMS):

from django.db.models.functions import Cast
from django.db.models import TextField

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'
Run Code Online (Sandbox Code Playgroud)

同样,它也适用于嵌套字段:

queryset = FooBarModel.objects.values(Cast('baz__some_datetime_field', TextField()))
Run Code Online (Sandbox Code Playgroud)

Func或者,也可以使用自定义(此处也特定于 Postgres,但可以针对任何其他 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'
Run Code Online (Sandbox Code Playgroud)


Yan*_*ann 6

extra()是 Django 旨在在未来某个时候弃用的旧 API。我会避免使用它。

请尝试以下操作:

from django.db.models import F, Func, Value, CharField

qs.annotate(
  formatted_date=Func(
    F('date'),
    Value('dd.MM.yyyy hh:mm'),
    function='to_char',
    output_field=CharField()
  )
)
Run Code Online (Sandbox Code Playgroud)

这仅适用于支持to_char 日期类型格式化功能的数据库。Postgres默认提供此功能。如果您使用MSSQL后端,则可以to_charFORMAT. 对于Oracle参考它们的文档等。

在对查询集进行评估后,这会将注释添加formatted_date到返回的查询集中的每个对象。


Ano*_*oop 5

qs = MyModel.objects.filter(name='me')
qs = qs.extra(select={'datestr':"DATE_FORMAT(activation_date, '%Y-%m-%d')"})
qs = qs.values_list('datestr')
Run Code Online (Sandbox Code Playgroud)

  • 第二行应该是:``qs = qs.extra(select={'datestr':"DATE_FORMAT(activation_date, '%%Y-%%m-%%d')"}) `` (2认同)