Skip to content

Commit

Permalink
Merge pull request #103 from Eastwu5788/2.1.1-dev
Browse files Browse the repository at this point in the history
remove chinese docs and part of annotation
  • Loading branch information
Eastwu5788 committed Jun 5, 2020
2 parents 319984a + 170dacb commit 94c72ed
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 54 deletions.
147 changes: 123 additions & 24 deletions DESCRIPTION.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,39 +26,36 @@ Pre-request
:alt: Im


欢迎您使用pre-request框架,pre-request致力于简化请求参数验证工作。为Flask的
网络请求参数验证提供了解决方案。
This framework is designed to validate params for Restful api request.

pre-request提供了非常方便的使用的方法,也提供了灵活的扩展接口方便您实现自定义的
业务逻辑。
We can validate complex struct and field, including Cross Field, Cross Struct

特点
----

1. 提供绝大部分常用的参数基础验证能力,也提供callback函数让用户自定义验证
2. 提供跨字段的、跨数据结构的参数验证能力,实现参数之间关联验证
3. 提供响应对象、格式化函数、过滤器等核心组件的自定义能力
4. 详细完善的测试用例,保证整体测试覆盖率高于90%
5. 丰富的example,演示了pre-request目前提供的所有能力
Install
-----------

安装
----
you can simply install it by:

::

pip install pre-request

快速使用
----------------
Document
----------

集成pre-request到您的请求中非常简单
Pre-request manual could be found at: https://pre-request.readthedocs.io/en/master/index.html


A Simple Example
------------------

This is very easy to use `pre-request` in your project

.. code-block:: python
from flask import Flask
from pre_request import pre
from pre_request import Rule
from pre_request import pre, Rule
app = Flask(__name__)
Expand All @@ -70,14 +67,116 @@ pre-request提供了非常方便的使用的方法,也提供了灵活的扩展
@pre.catch(args)
def hello_world(params):
from flask import g
return params == g.params
return str(params == g.params)
what happened in this code ?

1. Use `pre-request` library to import a global object `pre`
2. Define request params rule, `userId` must be type of `int` and required
3. Use `@pre.catch(req_params)` to filter input value
4. Use `~flask.g` or `def hello_world(params)` to get formatted input value。


Complex Example
-----------------

We use a very complex example to show the powerful of this framework

.. code-block:: python
from flask import Flask
from pre_request import pre, Rule
args = {
"userFirst": {
"userId": Rule(type=int, required=False),
"socialInfo": {
"gender": Rule(type=int, enum=[1, 2], default=1),
"age": Rule(type=int, gte=18, lt=80),
"country": Rule(required=True, deep=False)
}
},
"userSecond": {
"userId": Rule(type=int, required=False, neq_key="userFirst.userId"),
"socialInfo": {
"gender": Rule(type=int, enum=[1, 2], default=1, neq_key="userFirst.socialInfo.gender"),
"age": Rule(type=int, gte=18, lt=80, required_with="userFirst.socialInfo.age"),
"country": Rule(required=True, deep=False)
}
}
}
app = Flask(__name__)
app.config["TESTING"] = True
client = app.test_client()
@app.route("/structure", methods=["GET", "POST"])
@pre.catch(args)
def structure_handler(params):
return str(params)
if __name__ == "__main__":
resp = app.test_client().post("/structure", json={
"userFirst": {
"userId": "13",
"socialInfo": {
"age": 20,
}
},
"userSecond": {
"userId": 14,
"socialInfo": {
"age": 21
}
},
"country": "CN",
"userFirst.socialInfo.gender": 1,
"userSecond.socialInfo.gender": 2,
})
print(resp.get_data(as_text=True))
Use parse
-------------

We can use function `pre.parse` instead of decorator `@pre.catch()`

.. code-block:: python
args = {
"params": Rule(email=True)
}
@app.errorhandler(ParamsValueError)
def params_value_error(e):
return pre.fmt_resp(e)
@app.route("/index")
def example_handler():
rst = pre.parse(args)
return str(rst)
Contributing
--------------

How to make a contribution to Pre-request, see the `contributing`_.

.. _contributing: https://github.com/Eastwu5788/pre-request/blob/master/CONTRIBUTING.rst


Coffee
---------

Please give me a cup of coffee, thank you!

上面的代码中发生了什么呢?
BTC: 1657DRJUyfMyz41pdJfpeoNpz23ghMLVM3

1. 首先我们从 `pre-request` 库中引入全局 `pre` 对象,使用该对象来过滤用户参数
2. 我们定义了一个请求参数 `userId` 并规定该参数的目标类型为 `int` ,并且不允许为空
3. 使用 `@pre.catch(req_params)` 将参数规则赋值给装饰器,并装饰处理函数
4. 格式化后的参数置于 `~flask.g` 中,同时尝试将格式化后的参数置于原函数的 `params` 参数中。
ETH: 0xb098600a9a4572a4894dce31471c46f1f290b087


Links
Expand Down
31 changes: 1 addition & 30 deletions pre_request/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,92 +7,63 @@ class Rule: # pylint: disable=too-many-instance-attributes
"""

def __init__(self, **kwargs):
# 参数来源位置
self.location = kwargs.get("location", None)
# 字段目标数据类型
self.direct_type = kwargs.get("type", str)
# 不进行过滤,仅把参数加到结果集中
self.skip = kwargs.get("skip", False)
# 请求参数深度跟随
self.deep = kwargs.get("deep", True)
# 指定参数是否有多个,如果传入的是list时,multi=False会读取最后一个
self.multi = kwargs.get("multi", False)

# 当前字段是否是必填项
self.required = kwargs.get("required", True)
self.required_with = kwargs.get("required_with", None)

# 当前字段默认值,如果不允许为空,则次字段无意义
self.default = kwargs.get("default", None)
# 去除前后的空格
self.trim = kwargs.get("trim", False)

# 字段枚举值设置
self.enum = kwargs.get("enum", list())

# 正则表达式
self.reg = kwargs.get("reg", None)
# Email判断

self.email = kwargs.get("email", False)
# 手机号判断
self.mobile = kwargs.get("mobile", False)

# 判断字符串中包含某个子串
self.contains = kwargs.get("contains", list())
# 判断字符串包含任意子串
self.contains_any = kwargs.get("contains_any", list())
# 判断字符串中禁止包括某个子串
self.excludes = kwargs.get("excludes", list())
# 判断字符串开头
self.startswith = kwargs.get("startswith", None)
# 判断字符串结尾
self.endswith = kwargs.get("endswith", None)
# 字符串小写
self.lower = kwargs.get("lower", False)
# 字符串大写
self.upper = kwargs.get("upper", False)
# 是否是文件路径
# self.file = kwargs.get("file", False)
# 字符串分割
self.split = kwargs.get("split", None)

# 判断入参是否为ipv4/ipv6
self.ipv4 = kwargs.get("ipv4", False)
self.ipv6 = kwargs.get("ipv6", False)
self.mac = kwargs.get("mac", False)

# 判断入参是否为地理坐标 经度/维度
self.latitude = kwargs.get("latitude", False)
self.longitude = kwargs.get("longitude", False)

# 日期格式化字符串
self.fmt = kwargs.get("fmt", "%Y-%m-%d %H:%M:%S")

# 跨字段验证
self.eq_key = kwargs.get("eq_key", None)
self.neq_key = kwargs.get("neq_key", None)
self.gt_key = kwargs.get("gt_key", None)
self.gte_key = kwargs.get("gte_key", None)
self.lt_key = kwargs.get("lt_key", None)
self.lte_key = kwargs.get("lte_key", None)

# 等于/不等于
self.eq = kwargs.get("eq", None)
self.neq = kwargs.get("neq", None)

# 范围限定 direct_type 为数字时限定数字大小,为字符串时限定字符串长度
self.gt = kwargs.get("gt", None)
self.gte = kwargs.get("gte", None)
self.lt = kwargs.get("lt", None)
self.lte = kwargs.get("lte", None)

# key映射
self.key_map = kwargs.get("dest", None)

# 是否需要进行json解析
self.json_load = kwargs.get("json", False)

# 自定义处理callback, 在所有的filter处理完成后,通过callback回调给用户进行自定义处理
self.callback = kwargs.get("callback", None)

@property
Expand Down

0 comments on commit 94c72ed

Please sign in to comment.