Flask 如何验证前端传过来的数据

2023-09-06 09:19:49 +08:00
 XueXianqi

大家在用 Flask 的时候,是如何校验数据的类型和值的?

我之前用过 Django + DRF ,Django 的 Forms 和 DRF 的 Serializer 都很香,校验和处理数据

但是 Flask 有点让我发愁,手动用大量的 if 看起来费时费力,不太美观

有没有现成的第三方库可以用的,并且可以自定义抛出异常的类型并捕获

之前看过一些 FastAPI 用的 Pydantic 还有 Marshmallow

Pydantic 抛出的异常可能我不知道正确的打开方式,不太会用

比如说:

from enum import Enum

from pydantic import (
    BaseModel,
    Field,
)


class HolidayTypeEnum(str, Enum):
    ANNUAL_LEAVE = "annual_leave"
    SICK_LEAVE = "sick_leave"


class Holiday(BaseModel):
    holiday_name: str = Field(..., description="请填写假期名称")
    holiday_type: HolidayTypeEnum = Field(..., description="请填写假期类型")


data = {
    "holiday_name": "年假",
    "holiday_type": "annual_leave1",
}
holiday = Holiday(**data)

抛出的异常是:

pydantic.error_wrappers.ValidationError: 1 validation error for Holiday
holiday_type
  value is not a valid enumeration member; permitted: 'annual_leave', 'sick_leave' (type=type_error.enum; enum_values=[<HolidayTypeEnum.ANNUAL_LEAVE: 'annual_leave'>, <HolidayTypeEnum.SICK_LEAVE: 'sick_leave'>])

如何提示给前端到底错在哪里(之前手动校验的时候,是可以直接抛出指定异常,比如说 raise ValueError("假期类型错误,只能为 XXX 、XXX")

也许 Pydantic 是很好,但是我好像不太会用,有没有大佬有正确的打开方式,或者说其他可以拿来就用的第三方库

2158 次点击
所在节点    Python
16 条回复
BingoXuan
2023-09-06 09:24:48 +08:00
try except 捕获 ValidationError ,然后返回 http code 400 和错误信息

高级一点就是自己写个 middleware 处理
maocat
2023-09-06 09:33:59 +08:00
flask_marshmallow 很久之前用的了,不知道现在啥情况了
raptor
2023-09-06 09:34:31 +08:00
flask-restx 试试?
lambdaq
2023-09-06 09:34:39 +08:00
> Django 的 Forms 和 DRF 的 Serializer 都很香

说明你们数据校验需求真的很简单。
maocat
2023-09-06 09:35:27 +08:00
XueXianqi
2023-09-06 09:38:35 +08:00
@BingoXuan
我看了一下捕获到的 ValidationError ,内容是这样的:

ValidationError(
model='Holiday',
errors=[
{
'loc': (
'holiday_type',
),
'msg': "value is not a valid enumeration member; permitted: 'annual_leave', 'sick_leave'",
'type': 'type_error.enum',
'ctx': {
'enum_values': [
<HolidayTypeEnum.ANNUAL_LEAVE: 'annual_leave'>,
<HolidayTypeEnum.SICK_LEAVE: 'sick_leave'>,
],
},
},
],
)

具体的错误信息应该如何解析呢(比如说这里只有英文内容的 msg ,有类似于 Django 设置国际化,转换成中文的配置么)
XueXianqi
2023-09-06 09:40:27 +08:00
@lambdaq Django 的 Forms 只是初学 Django 的时候觉得好用,实际业务中是 用的 DRF 的 Serializer ,还是有很多自定义的 validator 的,不可能单纯地用原有的校验数据类型、长度等
mikurasa
2023-09-06 09:47:47 +08:00
Baloneo
2023-09-06 09:51:32 +08:00
```
def validate_schema(schema_class):
assert issubclass(schema_class, Schema) # Marshmallow

def decorator(view_func):
@functools.wraps(view_func)
def inner(*args, **kwargs):

if request.method == "GET":
form_data = request.args
else:
form_data = request.json
try:
data = schema_class().load(form_data)
_request_ctx_stack.top.schema_data = data
except ValidationError as e:
return error_json(
ResponseCode.ERROR, parse_err_messages(e), data=e.messages
)
return view_func(*args, **kwargs)

return inner

return decorator

@validate_schema(val.PostTestSchema)
def api_test():
device_id = current_schema_data.get('device_id')
```
cyber2077
2023-09-06 09:52:05 +08:00
用 wtforms
BingoXuan
2023-09-06 10:12:51 +08:00
@XueXianqi

pydantic 有例子说明怎么获取具体的 validation error https://docs.pydantic.dev/latest/errors/validation_errors/

国际化要看项目怎么做国际化了,最朴素就是自定义错误,自家处理国际化
rexyan
2023-09-06 10:47:47 +08:00
voluptuous + 装饰器
zcf0508
2023-09-06 10:59:52 +08:00
试试 apiflask
911061873
2023-09-06 14:28:00 +08:00
dayeye2006199
2023-09-06 23:25:31 +08:00
pydantic 的错误信息其实挺清楚的,只需要英文的话基本自己写个拆 error 的中间件就可以用了。

需要中文的话: https://pydantic-i18n.boardpack.org/
yudengqing
2023-09-07 09:24:53 +08:00
用 wtform 吧,也很方便

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/971283

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX