【问题标题】:Datetime filtering with SQLAlchemy isn't working使用 SQLAlchemy 进行日期时间过滤不起作用
【发布时间】:2023-04-05 14:41:01
【问题描述】:

基本上,我需要构建一个函数,该函数将根据给定日期过滤查询并返回新查询。我是 SQLAlchemy 的新手,我查找了类似的问题,但仍然遇到同样的错误:

`Don't know how to literal-quote value datetime.datetime(2018, 1, 1, 8, 3, 1, 438278)`

这是我的代码:

def filter_dates(query_obj, datecols, start = None, end = None):
        if end is None:
            end = datetime.datetime.now()
        if start is None:
            start = end - datetime.timedelta(weeks=12)
        print("%s to %s" % (start, end))
        for datecol in datecols:
            print("Filtrando datas!")
            query_obj = query_obj.filter(datecol >= start)
            query_obj = query_obj.filter(datecol <= end)
            ReevTable.print_query(query_obj)
        return query_obj

datecols 是一个 orm.attributes 对象。假设我有一个名为User 的对象,其Datetime 属性名为created_at。这是预期的行为:

query = session.query(Company.name, Company.created_at, Company.number_of_employees, Company.email_bounce_rate)
query = filter_dates(query_obj=query, datecols = [Company.created_at, Company.email_events.created_at])
query.all()

预期输出是一个包含仅在日期范围内创建的公司的表格,并且跳出率应仅在该指定日期范围内计算。这可能看起来很奇怪,但我计算的不仅仅是电子邮件,还有其他类型的交互,所以我需要输入一个属性列表而不仅仅是一个属性。这就是为什么我需要用一个方法来分离这个过滤。

我尝试过使用 pandas 的 datetime 和 timedelta、内置的 python datetime 模块以及带有 pd.to_datetime 的简单字符串,但没有成功。每次都会引发相同的错误。我的公司专栏在 DateTime 中,所以我不知道还能做什么。

class Company(Base)
    created_at = Column(DateTime, nullable=False)

我对 SQLAlchemy 完全陌生,我做错了什么?

完整的追溯:

`Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "reev-data-science/tables/reevtable.py", line 128, in import_data
    self.print_query(query_obj)
  File "reev-data-science/tables/reevtable.py", line 107, in print_query
    print(bcolors.OKBLUE + bcolors.BOLD + str(query_obj.statement.compile(compile_kwargs={"literal_binds":True})) + bcolors.ENDC)
  File "<string>", line 1, in <lambda>
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/elements.py", line 442, in compile
    return self._compiler(dialect, bind=bind, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/elements.py", line 448, in _compiler
    return dialect.statement_compiler(dialect, self, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 453, in __init__
    Compiled.__init__(self, dialect, statement, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 219, in __init__
    self.string = self.process(self.statement, **compile_kwargs)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 245, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/annotation.py", line 80, in _compiler_dispatch
    self, visitor, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 1815, in visit_select
    text, select, inner_columns, froms, byfrom, kwargs)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 1899, in _compose_select_body
    t = select._whereclause._compiler_dispatch(self, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 829, in visit_clauselist
    for c in clauselist.clauses)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 826, in <genexpr>
    s for s in
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 829, in <genexpr>
    for c in clauselist.clauses)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 829, in visit_clauselist
    for c in clauselist.clauses)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 826, in <genexpr>
    s for s in
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 829, in <genexpr>
    for c in clauselist.clauses)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 1080, in visit_binary
    return self._generate_generic_binary(binary, opstring, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 1113, in _generate_generic_binary
    self, eager_grouping=eager_grouping, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/visitors.py", line 81, in _compiler_dispatch
    return meth(self, **kw)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 1244, in visit_bindparam
    bindparam, within_columns_clause=True, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 1277, in render_literal_bindparam
    return self.render_literal_value(value, bindparam.type)
  File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/compiler.py", line 1295, in render_literal_value
    "Don't know how to literal-quote value %r" % value)
NotImplementedError: Don't know how to literal-quote value datetime.datetime(2018, 1, 1, 9, 24, 46, 54634)`

print_query() 方法:

`def print_query(query_obj):
    print(bcolors.OKBLUE + bcolors.BOLD + str(query_obj.statement.compile(compile_kwargs={"literal_binds":True})) + bcolors.ENDC)`

【问题讨论】:

  • 请包含完整的回溯。我怀疑你的ReevTable.print_query(query_obj) 是罪魁祸首,虽然你没有包括它的定义。
  • 对不起,我没有意识到这可能与此有关。我已经更新了帖子。
  • 是的,如果您检查回溯,您会注意到由于使用了文字绑定,导致异常的是打印查询的行为。 This 非常相关,值得一读。还要检查official documentation on the subject:“上述方法有一个警告,它只支持基本类型,例如整数和字符串”
  • 你是对的!太感谢了。您能否建议我以某种方式打印查询对象的语句,而不会丢失有关我正在输入的参数的信息?因为,如果我删除了 literal_binds,代码可以工作,但我看不到被过滤的实际日期
  • 链接的 Q/A 和文档(实际上它们是相同的文本)都建议对不支持呈现文字和实现 TypeDecorator.process_literal_param() 的类型使用自定义 TypeDecorator

标签: python datetime sqlalchemy


【解决方案1】:

在您的过滤子句中将datatime 对象转换为str

def filter_dates(query_obj, datecols, start = None, end = None):
        if end is None:
            end = datetime.datetime.now()
        if start is None:
            start = end - datetime.timedelta(weeks=12)
        print("%s to %s" % (start, end))
        for datecol in datecols:
            print("Filtrando datas!")
            query_obj = query_obj.filter(datecol >= str(start))
            query_obj = query_obj.filter(datecol <= str(end))
            ReevTable.print_query(query_obj)
        return query_obj

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    相关资源
    最近更新 更多