sqlalchemy:写入日期时间范围类型的 table

sqlalchemy: writing to a table with datetimerange type

我需要将一个范围时间数组写入 postresql 数据库。我有以下代码

from sqlalchemy.engine import create_engine
from datetime import datetime
from psycopg2.extras import DateTimeRange
from sqlalchemy_utils import DateTimeRangeType

engine = create_engine(ApplicationConfigs.database.url)
session = sessionmaker(bind=engine)()

class DBCourier(BaseModel):
    __tablename__ = 'couriers'
    
    id = Column(Integer, unique=True, nullable=False, primary_key=True)
    working_hours = Column(ARRAY(DateTimeRangeType))


data = DBCourier(
    id=2,
    working_hours=[DateTimeRange(datetime(1, 1, 1, 1, 1), datetime(2, 2, 2, 2, 2)),]
)
    
    
session.add(data)
session.commit()

写入时,datetimerange 类型转换为文本:

Traceback (most recent call last):
  File "...sqlalchemy\engine\base.py", line 1276, in _execute_context
    self.dialect.do_execute (
  File "...sqlalchemy\engine\default.py", line 608, in do_execute
    cursor.execute (statement, parameters)
psycopg2.errors.DatatypeMismatch: ERROR: column "working_hours" is of type tsrange [] and expression is text []
LINE 1: ..., working_hours) VALUES (2, ARRAY['[00...
                                                             ^
HINT: Rewrite or convert the expression.

但是写单值时不会出现这个问题:

engine = create_engine(ApplicationConfigs.database.url)
session = sessionmaker(bind=engine)()

class DBCourier(BaseModel):
   __tablename__ = 'couriers'

   id = Column(Integer, unique=True, nullable=False, primary_key=True)
   working_hours = Column(DateTimeRangeType)

data = DBCourier(
    id=2,
    working_hours=DateTimeRange(datetime(1, 1, 1, 1, 1), datetime(2, 2, 2, 2, 2))
)


session.add(data)
session.commit()

如何解决这个问题?

看起来这是 SQLAlchemy-utils 中的错误。如果您使用 SQLAlchemy 中的原生 TSRANGE,它工作正常:

from datetime import datetime
from psycopg2.extras import DateTimeRange
from sqlalchemy import Column, Integer, ARRAY, create_engine
from sqlalchemy.dialects.postgresql import TSRANGE
from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from config import dburl

Base = declarative_base()


class DBCourier(Base):
    __tablename__ = "couriers"

    id = Column(Integer, unique=True, nullable=False, primary_key=True)
    working_hours = Column(ARRAY(TSRANGE))


engine = create_engine(dburl, echo=True)

Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)

test = DBCourier(
    working_hours=[
        DateTimeRange(datetime(2021, 3, 25), None),
        DateTimeRange(datetime(2021, 3, 22), datetime(2021, 3, 25)),
    ]
)

Session = sessionmaker(engine)
db = Session()
db.add(test)
db.commit()