bigywater.tech
Flask · 116

Pydantic 在 Flask 中的使用

Pydantic 在 Flask 里怎么用?错误信息能直接返回给客户端吗?宽松模式会转换哪些输入?这篇把踩过的坑(包括我自己第一次写出的 500)和每种输入的结果逐项打印出来。

500
直接 jsonify(e.errors()) 遇到 bytes 的 input 或异常对象的 ctx 时的状态码
5.5
pydantic 对 int 字段报 int_from_float 错误,而 marshmallow 会截断
18.6 ms
逐个校验 10000 个字典的耗时

转换与错误

实测 · 本机执行输出
  合法(price 是字符串 "1.50")          → 通过 {'name': 'pen', 'qty': 3, 'price': Decimal('1.50'), 'tags': [], 'note': None}
  缺字段                            → qty: missing; price: missing
  多个字段出错                         → name: string_too_short; qty: greater_than_equal; price: decimal_parsing
  qty = "5"(字符串)                 → 通过 {'name': 'pen', 'qty': 5, 'price': Decimal('1.50'), 'tags': [], 'note': None}
  qty = 5.5                      → qty: int_from_float
  qty = 5.0                      → 通过 {'name': 'pen', 'qty': 5, 'price': Decimal('1.50'), 'tags': [], 'note': None}
  qty = True                     → 通过 {'name': 'pen', 'qty': 1, 'price': Decimal('1.50'), 'tags': [], 'note': None}
  多余字段 extra                     → 通过 {'name': 'pen', 'qty': 3, 'price': Decimal('1.50'), 'tags': [], 'note': None}
  tags 里有数字                      → tags.1: string_type
  一条错误的完整内容: {'type': 'greater_than_equal', 'loc': ('qty',), 'msg': 'Input should be greater than or equal to 0', 'input': -1, 'ctx': {'ge': 0}}

上一篇:Marshmallow 序列化;下一篇:大批量 JSON 响应。

bool 与严格模式

实测 · 本机执行输出
  flag='true'   → True
  flag='false'  → False
  flag='0'      → False
  flag='1'      → True
  flag='yes'    → True
  flag='off'    → False
  flag='abc'    → 错误
  flag=2        → 错误
  flag='maybe'  → 错误
  宽松(默认)         n 收到 "5"、5.0、True → [5, 5, 1]
  strict=True    n 收到 "5"、5.0、True → ['错误', '错误', '错误']

放进 Flask

实测 · 本机执行输出
  合法                                 → 200 {"age":3,"name":"ann"}
  age 越界                             → 422 {"errors":[{"ctx":{"le":150},"input":300,"loc":["age"],"msg":"Input should be less than or equal to 150","type":"less_than_equal",
  extra 被禁止                          → 422 {"errors":[{"input":1,"loc":["x"],"msg":"Extra inputs are not permitted","type":"extra_forbidden","url":"https://errors.pydantic.d
  非法 JSON                            → 500 <!doctype html> <html lang=en> <title>500 Internal Server Error</title> <h1>Internal Server Error</h1> <p>The server encountered a
  自定义校验器 ValueError                  → 500 <!doctype html> <html lang=en> <title>500 Internal Server Error</title> <h1>Internal Server Error</h1> <p>The server encountered a
  同上,errors(include_context=False, include_input=False) → 422 {"errors":[{"loc":["name"],"msg":"Value error, \u4fdd\u7559\u540d","type":"value_error"}]}
  非法 JSON,同样的 errors(...) 写法         → 422 {"errors":[{"loc":[],"msg":"Invalid JSON: EOF while parsing an object at line 1 column 1","type":"json_invalid"}]}
  非法 JSON,用 e.json()                 → 422 [{"type":"json_invalid","loc":[],"msg":"Invalid JSON: EOF while parsing an object at line 1 column 1","input":"{","ctx":{"error":"
  同上,用 e.json()                      → 422 [{"type":"value_error","loc":["name"],"msg":"Value error, 保留名","input":"admin","ctx":{"error":"保留名"}}]

查询参数

实测 · 本机执行输出
  ?ids=1&ids=2&page=3 用 to_dict(): 错误: ['list_type']
  自己用 getlist 处理 ids → ids=[1, 2] page=3

序列化

实测 · 本机执行输出
  model_dump(): {'id': 1, 'email': 'a@x.test', 'created': datetime.datetime(2026, 1, 2, 3, 4, 5), 'bal': Decimal('1.10')}
  model_dump(mode="json"): {'id': 1, 'email': 'a@x.test', 'created': '2026-01-02T03:04:05', 'bal': '1.10'}
  model_json_schema() 的 properties: ['id', 'email', 'password', 'created', 'bal'] | required: ['id', 'email', 'password', 'created', 'bal']

性能

实测 · 本机执行输出
  逐个 model_validate 18.6 ms;TypeAdapter 一次校验整个列表 14.6 ms;model_dump 10000 个 7.9 ms

分步演示

Pydantic 在 Flask 中
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.7 / Flask 3.1.3 / Werkzeug 3.1.9 / Jinja2 3.1.6 / SQLAlchemy 2.1.1 / gunicorn 26.2.0(都装在自己的虚拟环境里);大多数实验用 Flask 的 test_client(直接调用 WSGI 应用,不经过网络),需要真实 HTTP 时另起 gunicorn 或开发服务器(端口 9600 以上,本机 127.0.0.1);计时用 time.perf_counter,数字每次运行会有小幅抖动。pydantic 2.13.5
    • 没有验证:与 Flask-Pydantic、flask-openapi3 等封装库的行为、自定义类型与 discriminated union、模型继承与 computed_field、异步校验、pydantic-settings 读取配置
    京ICP备2026067502号-1京公网安备11010502063487号