Skip to content

WTForms Schema 规范 ​

概述 ​

Schema 层负责请求数据的校验。项目使用 WTForms 定义表单类,通过 validators 约束字段格式,框架在接收请求体时自动执行校验。

设计原则

  • 创建/编辑共用一个表单类,继承 BaseForm
  • 特殊操作单独建类(如状态更新、排序调整)
  • message 必填,用于返回给前端的错误信息
  • 唯一性校验通过自定义 validate_ 方法实现

BaseForm 继承 ​

以岗位模块为例,src/modules/system/position/schema.py 完整内容:

python
from wtforms import StringField, IntegerField
from wtforms.validators import DataRequired, Length, NumberRange

from src.common.forms.base_form import BaseForm


# ============================================================
# 岗位表单类
# ============================================================
class PositionForm(BaseForm):
    """岗位创建/编辑表单"""
    name = StringField('岗位名称', validators=[
        DataRequired(message='岗位名称不能为空'),
        Length(min=1, max=150, message='岗位名称长度必须在1-150个字符之间')
    ])
    status = IntegerField('岗位状态', validators=[
        DataRequired(message='岗位状态不能为空'),
        NumberRange(min=1, max=2, message='岗位状态必须是1或2')
    ])
    sort = IntegerField('岗位排序', validators=[
        DataRequired(message='岗位排序不能为空'),
        NumberRange(min=0, max=99999, message='岗位排序必须在0-99999之间')
    ])


# ============================================================
# 设置状态表单类
# ============================================================
class PositionStatusForm(BaseForm):
    """岗位状态更新表单"""
    id = IntegerField('岗位ID', validators=[
        DataRequired(message='岗位ID不能为空'),
        NumberRange(min=1, message='岗位ID必须大于0')
    ])
    status = IntegerField('岗位状态', validators=[
        DataRequired(message='岗位状态不能为空'),
        NumberRange(min=1, max=2, message='岗位状态必须是1或2')
    ])

Validator 选择表 ​

Validator作用示例
DataRequired必填字段,不允许空值DataRequired(message='不能为空')
Length字符串长度限制Length(min=1, max=150)
NumberRange数值范围限制NumberRange(min=1, max=2)
Optional可选字段Optional()
Email邮箱格式Email(message='邮箱格式不正确')
URLURL 格式URL(message='URL格式不正确')
Regexp正则表达式Regexp(r'^[a-zA-Z]+$')

自定义校验器 ​

唯一性校验 ​

python
from wtforms import ValidationError
from src.modules.system.position.repository import PositionRepository

class PositionForm(BaseForm):
    """岗位创建/编辑表单"""
    name = StringField('岗位名称', validators=[
        DataRequired(message='岗位名称不能为空'),
        Length(min=1, max=150, message='岗位名称长度必须在1-150个字符之间')
    ])

    def validate_name(self, field):
        """自定义校验:检查岗位名称是否已存在"""
        exclude_id = self.id.data if self.id.data else None
        if PositionRepository.exists_by([Position.name == field.data], exclude_id):
            raise ValidationError('岗位名称已存在')

跨字段校验 ​

python
class DateRangeForm(BaseForm):
    """日期范围表单"""
    start_date = DateField('开始日期', validators=[DataRequired()])
    end_date = DateField('结束日期', validators=[DataRequired()])

    def validate_end_date(self, field):
        """自定义校验:结束日期必须大于开始日期"""
        if field.data < self.start_date.data:
            raise ValidationError('结束日期必须大于开始日期')

在 Router 中使用 ​

python
from flask import request
from src.common.utils.request import parse_request_body

@position_blue.route('/add', methods=['POST'])
@check_permission('sys:position:add')
def add():
    """新增岗位"""
    from src.modules.system.position.service import add_position
    from src.modules.system.position.schema import PositionForm
    data = parse_request_body(request, PositionForm)
    return add_position(data)

错误响应格式 ​

校验失败时,框架自动返回标准错误响应:

json
{
    "code": 1,
    "data": null,
    "msg": "岗位名称不能为空",
    "ok": false
}

开发要点 ​

  1. 创建/编辑共用一个表单类:继承 BaseForm,利用其内置的可选 id 字段
  2. 特殊操作单独建类:如状态更新、排序调整等,只包含必要的字段
  3. 合理设置 Validator:DataRequired / Length / NumberRange 等,让框架自动校验
  4. message 必填:用于返回给前端的错误信息,方便调试
  5. 唯一性校验:通过自定义 validate_ 方法实现,使用 Repository 层的 exists_by 方法
  6. 字段名与前端一致:确保前后端字段名对应

总结 ​

WTForms Schema 通过 BaseForm 继承公共字段(id 等),使用 validators 声明约束,自定义 validate_ 方法实现唯一性校验。特殊操作单独建类,message 必填用于返回给前端的错误信息。

小蚂蚁云团队 · 提供技术支持