
Security News
NVD Quietly Sweeps 100K+ CVEs Into a “Deferred” Black Hole
NVD now marks all pre-2018 CVEs as "Deferred," signaling it will no longer enrich older vulnerabilities, further eroding trust in its data.
表单数据绑定验证框架,支持Tornado(默认)、aiohttp、sanic、flask,可自行扩展支持其它的python web框架
目前已支持的web框架
Web框架 | Python版本 | 备注 |
---|---|---|
Tornado >= 6.0.0 | python >= 3.6 | |
Aiohttp >= 3.6.0 | python >= 3.7 | aiohttp对python最低支持版本3.7 |
Sanic >= 19.3 | python >= 3.6 | |
Flask>=2.0.1 | python >= 3.6 |
# 已发布在pypi的地址
pip3 install xargs
pip3 install https://github.com/marcohong/xform/archive/v0.5.0.tar.gz
# 或者使用最新版本
pip3 install git+https://github.com/marcohong/xform.git
Flask示例,只支持2.0以上
from flask import request
from flask import Flask
from xform.httputil import HttpRequest
from xform.adapters.flask import FlaskRequest #引入Flask的适配器
from xform.form import SubmitForm
from xform import fields
HttpRequest.configure(request_proxy=FlaskRequest) # 全局设置Request的代理为FlaskRequest
app = Flask(__name__)
# 表单声明(也可以使用继承Form实现)
form = SubmitForm(
id=fields.Integer(required=True, _min=1),
name=fields.Str(required=True, length=(3, 20))
)
@app.route('/', methods=['GET', 'POST'])
async def index():
# 注意表单之前获取过body数据可能会影响get_data取不到数据(因为缓冲区数据已被flask删除)
# locations:获取数据方式仅限于指定的作用域,locations可以是str或者tuple
# 作用域: form/json/query/headers/cookies,组合使用例如locations=('form','json')
# data, error = await self.form.bind(self, locations='json')
data, error = await form.bind(request)
if error:
return {'error': error}
return {'data': data}
if __name__ == '__main__':
app.run(port=8888)
# curl -X POST http://127.0.0.1:8888/ -d '{"id": 12, "name": "hello1"}' -H "Content-type: application/json"
# curl -X POST http://127.0.0.1:8888/ -d 'id=2&name=hello2'
# curl http://127.0.0.1:8888/\?id\=12\&name\=hello3
Tornado示例,更多demo请查看examples文件夹
from xform import fields
from xform import schema
from xform.form import SubmitForm
# 使用Schema可结合fields.Nested嵌套对象,支持多层嵌套对象
class UserSchema(schema.Schema):
uid = fields.Integer(required=True)
name = fields.Username(required=True, length=(4, 20))
# group = fields.Nested(GroupSchema)
form = SubmitForm(
id=fields.Integer(required=True, _min=1),
name=fields.Str(required=True),
# when_field 当表单某一个字段的值在when_value中定义 则强制变为必填(required=True)
password = fields.Password(required=False, when_field='id', when_value=lambda x: x and int(x) > 10)
# 如果表单提交类型的是json按照字典方式传值即可,否则使用user.uid=xxx方式传值
user=fields.Nested(UserSchema, required=False)
)
async def index():
data, error = await form.bind(self)
# curl http://localhost:8888 -X POST -d "id=1&name=test&user.name=user&user.uid=2"
自定义的提示(3种方式)
'''
1.替换提示内容
'''
from xform.messages import ErrMsg
# ErrMsg.set_messages在导入fields/validator之前执行
ErrMsg.set_messages({'invalid_start_date': 'time invalid'})
from xform import fields
'''
2.使用国际化文件message.po
默认情况下是使用tornado的locale.translate('xxx')
请把messages.py定义的value翻译即可,例如:
msgid "Length must be between %s and %s" (注意%s不能少)
msgstr "长度必须在%s到%s之间"
'''
from xform import fields
# coding...
'''
3.替换提示内容,后再使用国际化,请根据第1步在导入fields/validator之前设置,
国际化文件message.po定义相对应替换后的内容即可
'''
demo
cd examples/
# test tornado
python3 test_tornado.py
# test aiohttp web
python3 test_aiohttp.py
# test sanic web
python3 test_sanic.py
...
import re
from typing import Optional, Any
from xform.fields import Integer, Str, VALUE_TYPES
from xform.form import SubmitForm
'''
实现_validate方法即可,如果返回值需要转换则重写get_value方法
'''
class UserField(Integer):
# 不需要转换,因为返回值是一个缓存对象
cvt_type = None
def add_err_msg(self) -> None:
self.err_msg.update({'not_exist': 'User does not exist'})
async def _validate(self,
value: VALUE_TYPES,
attr: str,
data: dict) -> Optional[dict]:
# 假设UserCache.get返回的是一个缓存对象
data = await UserCache.get(value)
# 错误时调用self.set_error('xxx')设置错误提示语,不需要返回内容,成功时返回内容
if not data:
self.set_error('not_exist')
else:
# 返回的是缓存对象
return data
class OrderNOField(Str):
regex = r'^[a-zA-Z0-9_]+$'
def add_err_msg(self) -> None:
self.err_msg.update({'invalid': 'Invalid order'})
def __init__(self,
*,
length: tuple = 20,
**kwargs: Any):
kwargs['length'] = length
super().__init__(**kwargs)
async def _validate(self,
value: VALUE_TYPES,
attr: str,
data: dict) -> Optional[str]:
ret = re.match(self.regex, value)
if not ret:
self.set_error('invalid')
return
return value
# user_id是表单提交的字段(data_key是可选的,如果为空则使用user作为表单字段)
form = SubmitForm(
user=UserField(data_key='user_id', required=True),
order_no=OrderNOField(required=True)
)
from xform.fields import Str
from xform.validate import Validator, ValidationError
#参考OneOf
class OneOf(Validator):
default_message = ErrMsg.get_message('invalid_option')
def __init__(self, choices: Union[list, tuple], error: str = None):
self.choices = choices
self.error = error or self.default_message
def __call__(self, value: Union[str, int]):
'''
call方法实现逻辑
'''
if value is None or value not in self.choices:
# 验证错误时请抛出ValidationError错误
raise ValidationError(self.error)
return value
# 使用validate
form = SubmitForm(
tag=Str(required=True, validate=OneOf(('bule', 'red', 'green')))
)
'''
Tornado为例
'''
from xform.httputil import BaseRequest
class TornadoRequest(BaseRequest):
def __init__(self, request):
super().__init__(request)
def get_argument(self,
name: str,
default: Any = None) -> Optional[str]:
return self.request.get_argument(name, default=default)
def get_from_header(self,
name: str,
default: Any = None) -> Optional[dict]:
return self.request.request.headers.get(name, default)
def translate(self, message: str) -> str:
return self.request.locale.translate(message)
# ...实现BaseRequest里面的方法,
# 详细实现请参考xform.adapters.tornado.TornadoRequest
# 启动web服务前设置一下xform的request代理(不设置默认Tornado),以aiohttp为例
from xform.httputil import HttpRequest
from xform.adapters.aiohttp import AioHttpRequest
HttpRequest.configure(request_proxy=AioHttpRequest)
# Coding...
xfrom
is offered under the MIT license.
FAQs
Binding form data validation framework.
We found that xargs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
NVD now marks all pre-2018 CVEs as "Deferred," signaling it will no longer enrich older vulnerabilities, further eroding trust in its data.
Research
Security News
Lazarus-linked threat actors expand their npm malware campaign with new RAT loaders, hex obfuscation, and over 5,600 downloads across 11 packages.
Security News
Safari 18.4 adds support for Iterator Helpers and two other TC39 JavaScript features, bringing full cross-browser coverage to key parts of the ECMAScript spec.