使用Tortoise ORM对接PostgreSQL的Time类型字段报错问题求解
针对Tortoise ORM适配PostgreSQL TIME类型字段的解决方案
问题根因是Tortoise ORM官方没有提供适配PostgreSQL原生TIME类型的字段,之前两种字段选型都和数据库实际字段类型不匹配:
- 使用CharField时,PostgreSQL的TIME类型字段期望接收time类型参数,字符串类型的输入会被底层驱动尝试读取
hour属性,触发str object has no attribute 'hour'错误 - 使用DatetimeField时,虽然补全假日期可以正常写入,但查询时PostgreSQL返回的是TIME类型结果,DatetimeField的ISO8601解析逻辑无法适配time类型对象,触发解析错误
最优解决方案:自定义适配PostgreSQL TIME类型的字段
1. 实现自定义字段类
from datetime import time from tortoise.fields import Field class PostgreSQLTimeField(Field, time): # 指定数据库端字段类型为TIME SQL_TYPE = "TIME" def to_db_value(self, value: time | str, instance) -> time: # 入库前自动将HH:MM:SS格式字符串转为time对象 if isinstance(value, str): return time.fromisoformat(value) return value def to_python_value(self, value: time | str) -> time: # 查询结果自动转为time对象返回 if isinstance(value, str): return time.fromisoformat(value) return value
2. 替换模型中的对应字段
class Carb_Ratio(models.Model): id = fields.UUIDField(pk=True, auto_generated=True) client_id = fields.UUIDField() ratio_type = fields.CharEnumField(RatioType) carb_ratio = fields.DecimalField(max_digits=10, decimal_places=2) # 替换为自定义时间字段 start_time = PostgreSQLTimeField() end_time = PostgreSQLTimeField() insulin_sensitivity = fields.DecimalField(max_digits=10, decimal_places=2) created_at = fields.DatetimeField(auto_now_add=True)
3. Pydantic模型适配
对应的Pydantic序列化/反序列化模型直接将start_time、end_time字段类型声明为time即可,前端传入HH:MM:SS格式的字符串会被Pydantic自动解析为time对象,无需额外补全假日期,读写都不会触发格式错误。
内容的提问来源于stack exchange,提问作者Ara
相关产品推荐
相关产品推荐

