如何在SQLModel中使用Pydantic的HttpUrl存储至PostgreSQL
解决SQLModel中Pydantic HttpUrl类型存入PostgreSQL的适配问题
问题背景
使用SQLModel 0.0.22、Pydantic 2.10.3、PostgreSQL 14.15,尝试将Pydantic的HttpUrl类型以字符串形式存入数据库,模型代码如下:
class Source(SQLModel, table=True): id: UUID | None = Field(default_factory=uuid4, primary_key=True) url: HttpUrl = Field(sa_type=AutoString)
执行时触发错误:
sqlalchemy.exc.ProgrammingError: (psycopg.ProgrammingError) cannot adapt type 'HttpUrl' using placeholder '%s' (format: AUTO)
问题原因
SQLModel向数据库写入数据时,直接传递了Pydantic的HttpUrl对象,而psycopg无法将该对象直接适配为PostgreSQL的字符串类型,导致报错。
解决方案
方法一:自定义SQLAlchemy类型(推荐,兼容性强)
创建自定义SQLAlchemy类型,负责HttpUrl与字符串的双向转换:
from sqlalchemy import TypeDecorator, String from pydantic import HttpUrl, parse_obj_as class HttpUrlType(TypeDecorator): impl = String cache_ok = True def process_bind_param(self, value, dialect): # 存入数据库时,将HttpUrl转为字符串 return str(value) if value else None def process_result_value(self, value, dialect): # 查询返回时,将字符串转回HttpUrl对象 return parse_obj_as(HttpUrl, value) if value else None
修改模型,使用自定义类型:
class Source(SQLModel, table=True): id: UUID | None = Field(default_factory=uuid4, primary_key=True) url: HttpUrl = Field(sa_type=HttpUrlType)
方法二:通过Pydantic序列化器转换
利用Pydantic序列化器,在写入数据库前自动将HttpUrl转为字符串:
from pydantic import HttpUrl, PlainSerializer class Source(SQLModel, table=True): id: UUID | None = Field(default_factory=uuid4, primary_key=True) url: HttpUrl = Field( sa_type=AutoString, # 序列化时将HttpUrl转为字符串 serializer=PlainSerializer(lambda x: str(x), return_type=str) )
验证
创建实例时传入符合URL格式的字符串,Pydantic会自动验证为HttpUrl对象;存入数据库时自动转为字符串存储;查询返回时,SQLModel会将字符串重新解析为HttpUrl对象,同时保留Pydantic的验证逻辑。
内容的提问来源于stack exchange,提问作者Casio991ms
相关产品推荐
相关产品推荐

