如何在FastAPI+PostgreSQL中禁用小数字的科学计数法
解决PostgreSQL极小数值返回科学计数法的问题
方案一:在PostgreSQL端直接格式化输出
通过SQL的to_char函数,查询时将numeric类型字段转换为指定格式的字符串,从源头避免前端触发科学计数法显示。
示例查询语句:
SELECT other_columns, -- FM参数用于去除前导空格,后面的数字位数根据你存储的小数精度调整,确保覆盖所有有效位 to_char(your_tiny_column, 'FM999999999999999.9999999999') AS your_tiny_column FROM data_row;
调整FastAPI中的查询代码,使用上述格式化后的字段即可,此时接口返回的是字符串类型的小数,前端直接显示就能得到0.000000022385这类格式。
如果不想每次写查询都重复格式化逻辑,可以创建视图封装转换逻辑:
CREATE VIEW formatted_data_row AS SELECT id, other_columns, to_char(your_tiny_column, 'FM999999999999999.9999999999') AS your_tiny_column FROM data_row;
之后FastAPI直接查询这个视图即可。
方案二:在FastAPI(Pydantic)层处理
通过修改Pydantic模型的序列化逻辑,将Decimal类型转换为非科学计数法的字符串或数值。
方法1:使用Pydantic Validator
修改你的Data_Read模型,针对目标字段添加格式化逻辑:
from pydantic import BaseModel, validator from decimal import Decimal class Data_Read(BaseModel): # 其他字段保持不变 your_tiny_column: Decimal @validator('your_tiny_column') def format_tiny_decimal(cls, value): # 保留10位小数(可根据实际存储精度调整),去除末尾多余的0和小数点 formatted = format(value, '.10f') if '.' in formatted: formatted = formatted.rstrip('0').rstrip('.') return formatted class Config: orm_mode = True
这样接口返回的该字段会是字符串格式的普通小数,前端无需额外处理。
方法2:自定义JSON编码器
全局配置FastAPI的JSON序列化逻辑,统一处理Decimal类型:
from fastapi import FastAPI from decimal import Decimal import json from sqlalchemy import select from sqlalchemy.orm import Session import models import database app = FastAPI() def custom_decimal_encoder(obj): if isinstance(obj, Decimal): formatted = format(obj, '.10f') if '.' in formatted: formatted = formatted.rstrip('0').rstrip('.') return formatted return obj.__dict__ if hasattr(obj, '__dict__') else obj @app.get("/data", tags=["DataModel"]) async def getall_data(): with Session(database.engine) as session: query = select(models.data_row) results = session.exec(query).all() # 使用自定义编码器序列化结果 return json.loads(json.dumps(results, default=custom_decimal_encoder))
注意:此方法需要去掉response_model=List[models.Data_Read],或者调整模型中对应字段的类型为str以匹配序列化后的结果。
内容的提问来源于stack exchange,提问作者Uzair A.
相关产品推荐
相关产品推荐

