如何将Django Ninja错误转为可用于API响应的Schema?
Django Ninja API错误响应Schema配置问题解决方法
问题描述
使用Django Ninja开发API时,配置路由响应类型时遇到报错,代码示例如下:
from ninja import Schema from ninja.errors import HttpError, ValidationError class MyOutSchema(Schema): # 省略Schema字段定义 pass @router.get("/", response={200: MyOutSchema, 404:XXX, 429:XXX, 400:XXX}) def my_api(request, params): # 可能抛出HttpError或ValidationError的业务代码 pass
直接将HttpError或ValidationError作为响应类型时,生成接口文档会触发以下错误:
[14:13:01] [DJANGO] @router.get( [14:13:01] [DJANGO] ^^^^^^^^^^^ [14:13:01] [DJANGO] File "/home/Work/web-framework/.venv/lib/python3.11/site-packages/ninja/router.py", line 239, in decorator [14:13:01] [DJANGO] self.add_api_operation( [14:13:01] [DJANGO] File "/home/Work/web-framework/.venv/lib/python3.11/site-packages/ninja/router.py", line 288, in add_api_operation [14:13:01] [DJANGO] path_view.add_operation( [14:13:01] [DJANGO] File "/home/Work/web-framework/.venv/lib/python3.11/site-packages/ninja/operation.py", line 306, in add_operation [14:13:01] [DJANGO] operation = OperationClass( [14:13:01] [DJANGO] ^^^^^^^^^^^^^^^ [14:13:01] [DJANGO] File "/home/Work/web-framework/.venv/lib/python3.11/site-packages/ninja/operation.py", line 75, in __init__ [14:13:01] [DJANGO] self.response_models = self._create_response_model_multiple(response) [14:13:01] [DJANGO] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [14:13:01] [DJANGO] File "/home/Work/web-framework/.venv/lib/python3.11/site-packages/ninja/operation.py", line 241, in _create_response_model_multiple [14:13:01] [DJANGO] result[code] = self._create_response_model(model) [14:13:01] [DJANGO] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [14:13:01] [DJANGO] File "/home/Work/web-framework/.venv/lib/python3.11/site-packages/ninja/operation.py", line 248, in _create_response_model [14:13:01] [DJANGO] return type("NinjaResponseSchema", (Schema,), attrs) [14:13:01] [DJANGO] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [14:13:01] [DJANGO] File "/home/Work/web-framework/.venv/lib/python3.11/site-packages/ninja/schema.py", line 145, in __new__ [14:13:01] [DJANGO] result = super().__new__(cls, name, bases, namespace, **kwargs) [14:13:01] [DJANGO] ^ [14:13:01] [DJANGO] ^ [14:13:01] [DJANGO] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [14:13:01] [DJANGO] File "pydantic/main.py", line 197, in pydantic.main.ModelMetaclass.__new__ [14:13:01] [DJANGO] File "pydantic/fields.py", line 506, in pydantic.fields.ModelField.infer [14:13:01] [DJANGO] File "pydantic/fields.py", line 436, in pydantic.fields.ModelField.__init__ [14:13:01] [DJANGO] File "pydantic/fields.py", line 557, in pydantic.fields.ModelField.prepare [14:13:01] [DJANGO] File "pydantic/fields.py", line 831, in pydantic.fields.ModelField.populate_validators [14:13:01] [DJANGO] File "pydantic/validators.py", line 765, in find_validators [14:13:01] [DJANGO] RuntimeError: no validator found for <class 'ninja.errors.ValidationError'>, see `arbitrary_types_allowed` in Config
尝试用None替代XXX也无效,需要解决如何将Ninja错误对象转为可Schema化的类,或正确配置错误响应类型。
解决方案
Django Ninja要求响应类型必须是继承自Schema的类,错误异常类不符合要求,可通过以下两种方式解决:
1. 自定义错误响应Schema
针对不同错误类型创建匹配Ninja默认返回格式的Schema:
from ninja import Schema # 通用错误Schema,对应HttpError返回格式 class ErrorSchema(Schema): detail: str # 验证错误Schema,对应ValidationError返回格式 class ValidationErrorSchema(Schema): detail: list[dict[str, str]]
在路由中使用这些Schema:
@router.get("/", response={ 200: MyOutSchema, 404: ErrorSchema, 429: ErrorSchema, 400: ValidationErrorSchema }) def my_api(request, params): # 业务代码示例 # raise HttpError(404, "资源不存在") # raise ValidationError({"name": "不能为空"}) pass
2. 复用Ninja内置错误Schema(推荐)
Django Ninja内部已定义好标准错误Schema,可直接导入使用:
from ninja.errors import ErrorSchema, ValidationErrorSchema
直接在路由中引用:
@router.get("/", response={ 200: MyOutSchema, 404: ErrorSchema, 429: ErrorSchema, 400: ValidationErrorSchema }) def my_api(request, params): # 业务代码 pass
注:不同版本的Django Ninja可能调整内置Schema的命名或导入路径,若找不到则使用自定义方式。
问题根源
HttpError和ValidationError是异常类而非Schema类,Ninja生成OpenAPI文档时需要基于Schema解析响应结构,异常类无法被底层依赖的Pydantic识别为有效数据模型,因此会抛出找不到验证器的错误。
内容的提问来源于stack exchange,提问作者CrUncheSSH
相关产品推荐
相关产品推荐

