在django queryset.values_list()中将日期时间字段转换为字符串

wwodge7n  于 2022-12-01  发布在  Go
关注(0)|答案(9)|浏览(267)

我有一个查询集,如下所示:

qs = MyModel.objects.filter(name='me').values_list('activation_date')

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

n3ipq98p

n3ipq98p1#

https://docs.djangoproject.com/en/2.2/ref/models/fields/#datetimefield
一个日期和时间,在Python中由datetime.datetime示例表示。
可以直接转换DateTimeField得到它的字符串表示:

str(obj)
# obj = qs[0][0] ? or qs[0][1] ?

您将得到如下结果(在本例中,我使用datetime.datetime.now(),因为DateTimeFielddatetime.datetime表示,这是相同的行为):

>>> now = datetime.datetime.now()
>>> str(now)
'2013-06-26 00:14:26.260524'

如果您想要较少信息或以其他模式格式化,您可以使用strftime()函数来格式化它们。请参阅:

>>> now.strftime('%Y-%m-%d %H:%M')
'2013-06-26 00:14'
2wnc66cl

2wnc66cl2#

extra在Django 2.0中已过时

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

foo_bar = FooBarModel.objects.annotate(
    str_datetime=Cast(
        TruncSecond('some_datetime_field', DateTimeField()), CharField()
    )
).values('str_datetime').first()

结果为

foo_bar.str_datetime:
(str)'2014-03-28 15:36:55'

我还想提一下,你可以格式化它,以及以任何方式,你想像:

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()

结果为

foo_bar.str_datetime:
(str)'Days: 28 Hours: 15'
pkln4tw6

pkln4tw63#

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()
  )
)

这仅适用于支持to_chardate type formatting function的数据库。默认情况下,Postgres提供此函数。

  • 如果您使用MSSQL后端,则可以将to_charFORMAT交换。
  • 对于MySQL,请使用DATE_FORMAT
  • 有关Oracle的信息,请参阅他们的文档等。

在对查询集求值之后,这将向返回的查询集中的每个对象添加注解formatted_date

7jmck4yq

7jmck4yq4#

如果你使用Postgres,你可以这样做(date format options here)。解决方案依赖于数据库,但它肯定比在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')

我确信MySQL有一些与Postgres的to_char等效的功能,但您必须自己找到,因为我不是MySQL的人。

hujrc8aj

hujrc8aj5#

非常惊讶地看到没有人建议将其转换为简单的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'

类似地,它也适用于嵌套字段:

queryset = FooBarModel.objects.values(Cast('baz__some_datetime_field', TextField()))

或者,也可以使用自定义的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'
vvppvyoh

vvppvyoh6#

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

jdzmm42g7#

您也可以使用map函数将queryset中的日期转换为字符串。示例:

qs = MyModel.objects.filter(name='me').values_list('activation_date', flat=True)
data = map(str, qs)
hivapdat

hivapdat8#

我是这样做的

.annotate(date_str=ExpressionWrapper(
            Func(F('date'), Value('%d/%m/%Y %H:%i'), function='DATE_FORMAT'), output_field=CharField()
        ))
luaexgnf

luaexgnf9#

如果你只做过一次,请参考Yannic Hamann的答案。然而,如果你发现自己经常从数据库转换为str,你可以将Func定义为一个类,以避免输入output_field和函数。

class DateToChar(models.Func):
    """
    Custom Func expression to convert datetimes to str's in database query

    Params for initializer
    ------
    expression_1
        expression resulting in a date: ex: F('date')
    expression_2
        Format string as an expression: Value('YYYY-MM-DD')
    """
    arity = 2
    function = 'to_char'
    output_field = models.CharField()

请注意,函数会根据数据库后端而改变。这是为Postgres编写的。
这可以像这样使用

qs = qs.annotate(date_str=DateToChar(F('date'), Value('YYYY-MM-DD'))

或与任何产生日期/日期时间/整数/浮点数/十进制字段的表达式(请参阅Postgres to_char。因数据库而异)和产生字符字段或文本字段的表达式一起使用。
有关详细信息,请参阅Func文档

相关问题