SQLAlchemy返回奇怪的数据

时间:2018-07-17 21:02:00

标签: python sqlalchemy

我正在尝试从表格中导出日期。我只想拉出原始创建的对象。

我正在运行以下查询:

return model.Session.query(cls).filter(cls.issue_id == issue_id).order_by(desc("created")).first()

但是它照原样返回整个记录,我不知道如何导出创建的记录。

<IssueComment id=32 comment=ay user_id=578042a3-d879-4b32-96a9-10f9aabe152c issue_id=19 created=2018-07-17 20:17:09.653809 visibility=visible abuse_status=0>

如果我尝试调用在cls.created中创建的

return model.Session.query(cls.created).filter(cls.issue_id == issue_id).order_by(desc("created")).first()

并导出一个奇怪的日期时间版本。我只想要原始版本

(datetime.datetime(2018, 7, 17, 20, 17, 9, 653809),)

如何将创建的值导出为原始字符串?

2 个答案:

答案 0 :(得分:3)

如果该列是日期时间列,则原始值不是字符串,而是…日期时间。

在大多数数据库引擎中,实际上,存储在数据库中的datetime列的 actual 原始值是某种数字。例如,在Microsoft SQL Server中,IIRC是自1901年以来的64位十微秒整数。但是您不想要该数字。你会怎么做?

如果您想要某种特定格式的字符串,您当然可以要求数据库将其格式化为可接受的任何字符串格式,但是为什么呢?

您的引擎和/或SQLAlchemy已将datetime值表示为Python datetime对象。与字符串相比,它更小,从数据库传递的速度更快,并且更灵活(例如,您可以使用它们进行比较和算术)。

您始终可以将其格式化为所需的任何字符串格式。例如:

>>> d = datetime.datetime(2018, 7, 17, 20, 17, 9, 653809)
>>> str(d)
'2018-07-17 20:17:09.653809'
>>> d.isoformat()
'2018-07-17T20:17:09.653809'
>>> d.strftime('%Y%m%d%H%M%S')
'20180717201709'
>>> d.strftime('%m/%d/%Y %I:%M %p%S')
'07/17/18 08:18 PM'

…等等。

答案 1 :(得分:3)

SqlAlchemy查询属性(而不是整个模型)返回KeyedTuples,其行为类似于namedtuple。像普通的Python元组一样,带有单个元素的tuple由尾随逗号构成。这就是为什么您的结果(datetime.datetime(2018, 7, 17, 20, 17, 9, 653809),)显示datetime对象后跟逗号的原因。

>>> row = session.query(User.creation_timestamp).first()
>>> row
(datetime.datetime(2018, 4, 22, 9, 20, 56),)  # <- trailing comma because it's a tuple

可以通过索引访问值

>>> row[0]
datetime.datetime(2018, 4, 22, 9, 20, 56)

或按名称

>>> row.creation_timestamp
datetime.datetime(2018, 4, 22, 9, 20, 56)

这些值是具有所有常用方法的python对象

>>> row.creation_timestamp.isoformat()
'2018-04-22T09:20:56'
>>> str(row.creation_timestamp)
'2018-04-22 09:20:56'

tutorial.first()

有点令人困惑
  

应用一个限制,并返回第一个结果作为标量

该示例显示了一个返回的单个对象,如下所示:

>>> q = session.query(User).first()
>>> q
<User object at 0x7f97d8c6b590>

而首先通过属性调用查询将返回包装在元组中的值。如果您将元组视为结果集中的一行,这是有道理的。如果您在查询中调用.all(),则会得到一个元组(行)列表。如果您在查询中调用.limit(1).all(),则会得到一个包含单个元组的列表。因此,当您致电.first()时,您将从.limit(1).all()获得第一个结果,这是一个元组。

>>> row = session.query(User.creation_timestamp).all()
>>> row
[(datetime.datetime(2018, 4, 22, 9, 20, 56),), (datetime.datetime(2018, 4, 22, 9, 20, 56),), ...]

>>> row = session.query(User.creation_timestamp).limit(1).all()
>>> row
[(datetime.datetime(2018, 4, 22, 9, 20, 56),)]

>>> row = session.query(User.creation_timestamp).first()
>>> row
(datetime.datetime(2018, 4, 22, 9, 20, 56),)