36

我有一个查询集,例如:

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

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

4

9 回答 9

30

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()因为 aDateTimeFielddatetime.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'
于 2013-06-26T03:32:03.407 回答
17

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'
于 2018-01-29T14:40:32.787 回答
10

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_char 日期类型格式化功能的数据库。Postgres默认提供此功能。

  • 如果您使用MSSQL后端,则可以to_char使用FORMAT.
  • MySQL使用DATE_FORMAT
  • Oracle查阅他们的文档等。

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

于 2020-03-30T05:41:13.043 回答
9

如果您使用的是 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')

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

于 2013-09-11T19:42:06.413 回答
5
qs = MyModel.objects.filter(name='me')
qs = qs.extra(select={'datestr':"DATE_FORMAT(activation_date, '%Y-%m-%d')"})
qs = qs.values_list('datestr')
于 2016-05-09T15:31:40.713 回答
4

很惊讶地看到没有人建议将演员阵容简单化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'
于 2019-10-29T23:44:36.690 回答
2

我是这样做的

.annotate(date_str=ExpressionWrapper(
            Func(F('date'), Value('%d/%m/%Y %H:%i'), function='DATE_FORMAT'), output_field=CharField()
        ))
于 2019-04-02T11:39:16.197 回答
2

map您还可以使用函数将查询集中的日期转换为字符串。例子:

qs = MyModel.objects.filter(name='me').values_list('activation_date', flat=True)
data = map(str, qs)
于 2017-07-19T09:55:40.893 回答
0

如果您这样做一次,请参阅 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。因数据库而异)和导致 CharField 或 TextField 的表达式。

有关详细信息,请参阅Func文档

于 2021-11-30T22:19:14.293 回答