表单验证
表单验证
基于快速上手中的最小应用,本文档将展示如何为您的 GMSSH Python SDK 添加强大的表单验证功能。
表单验证特性
- 基于
WTForms
的强大验证 - 原生轻量级表单系统(2.1.7+)
- 国际化错误提示支持
- 自定义验证器扩展
基础表单验证
让我们在快速上手的基础应用上添加表单验证功能:
# main.py
import asyncio
from simplejrpc.app import ServerApplication
from simplejrpc.response import jsonify
from simplejrpc import StringField, RequireValidator
# 创建应用实例
app = ServerApplication("app.socket")
class EchoForm(BaseForm):
message = StringField(
validators=[RequireValidator(message="消息内容不能为空")]
)
@app.route(name="echo", form=EchoForm)
async def echo(message: str,lang: str):
"""带验证的回声接口"""
return jsonify(
data=f"收到消息: {message}",
msg="消息已处理"
)
# 原有的简单接口(无验证)
@app.route(name="hello")
async def hello():
"""简单的问候接口"""
return jsonify(data="Hello, GMSSH!", msg="请求成功")
if __name__ == "__main__":
asyncio.run(app.run())
自动验证
当表单验证失败时,框架会自动返回标准错误响应,无需手动编写验证逻辑。
自定义验证器
当内置验证器无法满足需求时,可以创建自定义验证器。让我们扩展基础应用,添加一个禁用词验证器:
# main.py (在基础版本上添加自定义验证器)
import asyncio
from simplejrpc import StringField, RequireValidator, Validator
from simplejrpc.app import ServerApplication
from simplejrpc.response import jsonify
from simplejrpc.exceptions import ValueError
# 创建应用实例
app = ServerApplication("app.socket")
# 自定义验证器:禁用词检查
class ContentFilterValidator(Validator):
def __init__(self, forbidden_words=None, message="消息包含禁用内容"):
self.forbidden_words = forbidden_words or ["spam", "广告", "违规"]
self.message = message
def validator(self, form, field):
message_lower = field.data.lower()
for word in self.forbidden_words:
if word.lower() in message_lower:
raise ValueError(f"{self.message}: 包含禁用词 '{word}'")
# 添加自定义验证器
class EchoForm(BaseForm):
message = StringField(validators=[RequireValidator("消息不能为空"),ContentFilterValidator(message="消息校验错误")])
# 保留原有的简单接口
@app.route(name="echo", form=EchoForm) # 无验证版本
async def echo(message: str):
"""简单回声接口(无验证)"""
return jsonify(
data=f"收到消息: {message}",
msg="消息已处理"
)
@app.route(name="hello")
async def hello():
"""简单的问候接口"""
return jsonify(data="Hello, GMSSH!", msg="请求成功")
if __name__ == "__main__":
asyncio.run(app.run())
内置验证器参考
simplejrpc
提供了丰富的内置验证器,可以满足大部分常见的验证需求:
原生表单系统(推荐)
新特性 (v2.1.7+)
从 2.1.7 版本开始,SDK 提供了更轻量级的原生表单验证系统,无需依赖 WTForms,支持国际化错误提示。
原生系统优势
- 轻量级:无外部依赖,包体积更小
- 国际化:内置多语言错误提示支持
- 高性能:专为 GMSSH 优化的验证引擎
- 易扩展:简单的验证器接口
基础使用示例
# main.py (原生表单系统)
import asyncio
import os
from simplejrpc.app import ServerApplication
from simplejrpc import StringField, IntegerField
from simplejrpc.response import jsonify
from simplejrpc import BaseForm, RequireValidator
from simplejrpc import TextMessage
# 创建应用实例
app = ServerApplication("app.socket")
# 使用原生表单系统
class UserProfileForm(BaseForm):
username = StringField(
validators=[RequireValidator(TextMessage("USERNAME_REQUIRED"))]
)
age = IntegerField(
validators=[RequireValidator(TextMessage("AGE_REQUIRED"))]
)
@app.route(name="update_profile", form=UserProfileForm)
async def update_profile(username: str, age: int):
"""更新用户资料"""
return jsonify(
data={
"username": username,
"age": age,
"updated_at": "2024-01-01T00:00:00Z"
},
msg="用户资料更新成功"
)
@app.route(name="hello")
async def hello():
"""简单的问候接口"""
return jsonify(data="Hello, GMSSH!", msg="请求成功")
if __name__ == "__main__":
asyncio.run(app.run())
字段类型说明
字段类型 | 描述 | 验证规则 |
---|---|---|
StringField | 字符串字段 | 必须为字符串类型,不能为空 |
IntegerField | 整数字段 | 必须为整数类型 |
RequireValidator | 必填验证器 | 字段不能为空或 null |
国际化配置
原生表单系统支持多语言错误提示,您可以创建语言配置文件:
配置文件示例
# zh-CN.ini (中文配置)
USERNAME_REQUIRED="用户名不能为空"
AGE_REQUIRED="年龄不能为空"
INVALID_FORMAT="格式不正确"
# en-US.ini (英文配置)
USERNAME_REQUIRED="Username is required"
AGE_REQUIRED="Age is required"
INVALID_FORMAT="Invalid format"
错误响应示例
当验证失败时,系统会返回标准的错误响应:
{
"jsonrpc": "2.0",
"result": {
"code": 400,
"meta": {
"endpoint": "update_profile",
"close": 1
},
"data": null,
"msg": "用户名不能为空: username"
},
"id": 1
}
客户端请求示例
{
"jsonrpc": "2.0",
"method": "update_profile",
"params": {
"lang": "zh-CN",
"username": "",
"age": 25
},
"id": 1
}
最佳实践
开发建议
- 验证器组合:通过
validators=[]
列表组合多个验证器,验证按顺序执行 - 自定义验证器:将常用验证逻辑封装为自定义验证器,提高代码复用性
- 错误消息:为每个验证器提供清晰的错误消息,提升用户体验
- 版本选择:推荐使用 2.1.7+ 原生表单系统,更轻量
补充
注意
需要注意如果参数校验期待得到字符串类型,但是传入的是整数类型,会导致抛出sdk 内部错误,我们校验使用err_msg进行错误修改。
示例:
# main.py
import asyncio
from simplejrpc.app import ServerApplication
from simplejrpc.response import jsonify
from simplejrpc import StringField, RequireValidator
# 创建应用实例
app = ServerApplication("app.socket")
class EchoForm(BaseForm):
message = StringField(
validators=[RequireValidator(message="消息内容不能为空")],err_msg="消息内容必须为字符串"
)
@app.route(name="echo", form=EchoForm)
async def echo(message: str,lang: str):
"""带验证的回声接口"""
return jsonify(
data=f"收到消息: {message}",
msg="消息已处理"
)
# 原有的简单接口(无验证)
@app.route(name="hello")
async def hello():
"""简单的问候接口"""
return jsonify(data="Hello, GMSSH!", msg="请求成功")
if __name__ == "__main__":
asyncio.run(app.run())