V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
XueXianqi
V2EX  ›  Python

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

  •  1
     
  •   XueXianqi · 2023-09-06 09:19:49 +08:00 · 2115 次点击
    这是一个创建于 444 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大家在用 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 是很好,但是我好像不太会用,有没有大佬有正确的打开方式,或者说其他可以拿来就用的第三方库

    16 条回复    2023-09-07 09:24:53 +08:00
    BingoXuan
        1
    BingoXuan  
       2023-09-06 09:24:48 +08:00
    try except 捕获 ValidationError ,然后返回 http code 400 和错误信息

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

    说明你们数据校验需求真的很简单。
    maocat
        5
    maocat  
       2023-09-06 09:35:27 +08:00
    XueXianqi
        6
    XueXianqi  
    OP
       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
        7
    XueXianqi  
    OP
       2023-09-06 09:40:27 +08:00
    @lambdaq Django 的 Forms 只是初学 Django 的时候觉得好用,实际业务中是 用的 DRF 的 Serializer ,还是有很多自定义的 validator 的,不可能单纯地用原有的校验数据类型、长度等
    mikurasa
        8
    mikurasa  
       2023-09-06 09:47:47 +08:00
    Baloneo
        9
    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
        10
    cyber2077  
       2023-09-06 09:52:05 +08:00 via Android
    用 wtforms
    BingoXuan
        11
    BingoXuan  
       2023-09-06 10:12:51 +08:00
    @XueXianqi

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

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

    需要中文的话: https://pydantic-i18n.boardpack.org/
    yudengqing
        16
    yudengqing  
       2023-09-07 09:24:53 +08:00 via iPhone
    用 wtform 吧,也很方便
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2940 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 08:15 · PVG 16:15 · LAX 00:15 · JFK 03:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.