该模块为验证查询参数提供了一个方便的api。

qval的Python项目详细描述


qval查询参数验证库

CircleCIDocumentation StatuscodecovPyPI versionCode style: black

安装

$ pip install qval

基本用法

您可以将qval用作函数和装饰器。函数validate()接受3个位置参数和1个名为:

# qval.pydefvalidate(# Request instance. Must be a dictionary or implement request interface.request:Union[Request,Dict[str,str]],# Dictionary of (param_name -> `Validator()` object).validators:Dict[str,Validator]=None,# Provide true if you want to access all parameters of the request in the context.box_all:bool=True,# Factories that will be used to convert parameters to python objects (param -> [callable[str] => object]).**factories,)->QueryParamValidator:

假设您有一个restful计算器,它的端点名为/api/divide。您可以使用validate() 自动将参数转换为python对象,然后验证它们:

fromqvalimportvalidate...defdivision_view(request):"""    GET /api/divide?    param a     : int    param b     : int, nonzero    param token : string, length = 12    Example: GET /api/divide?a=10&b=2&token=abcdefghijkl -> 200, {"answer": 5}    """# Parameter validation occurs in the context manager.# If validation fails or user code throws an error, context manager# will raise InvalidQueryParamException or APIException respectively.# In Django Rest Framework, these exceptions will be processed and result # in error codes (400 and 500) on the client side.params=(# `a` and `b` must be integers# Note: in order to get a nice error message on the client side,# you factory should raise either ValueError or TypeErrorvalidate(request,a=int,b=int)# `b` must be anything but zero.nonzero("b")# The `transform` callable will be applied to parameter before the check.# In this case we'll get `token`'s length and check if it is equal to 12..eq("token",12,transform=len))# validation starts herewithparamsasp:returnResponse({"answer":p.a//p.b})
//GET/api/divide?a=10&b=2&token=abcdefghijkl//Browser:{"answer":5}

向此终结点发送b=0将在客户端产生以下消息:

//GET/api/divide?a=10&b=0&token=abcdefghijkl{"error":"Invalid `b` value: 0."}


如果有许多参数和自定义验证器,最好使用@qval()装饰器:

# validators.pyfromdecimalimportDecimalfromqvalimportValidator,QvalValidationError...defprice_validator(price:int)->bool:"""    A predicate to validate `price` query parameter.    Provides custom error message.    """ifprice<=0:# If price does not match our requirements, we raise QvalValidationError() with a custom message.# This exception will be handled in the context manager and will be reraised# as InvalidQueryParamException() [HTTP 400].raiseQvalValidationError(f"Price must be greater than zero, got \'{price}\'.")returnTruepurchase_factories={"price":Decimal,"item_id":int,"token":None}purchase_validators={"token":Validator(lambdax:len(x)==12),# Validator(p) can be omitted if there is only one predicate:"item_id":lambdax:x>=0,"price":price_validator,}# views.pyfromqvalimportqvalfromvalidatorsimport*...# Any function or method wrapped with `qval()` must accept request as # either first or second argument, and parameters as last.@qval(purchase_factories,purchase_validators)defpurchase_view(request,params):"""    GET /api/purchase?    param item_id : int, positive    param price   : float, greater than zero    param token   : string, len == 12    Example: GET /api/purchase?item_id=1&price=5.8&token=abcdefghijkl    """print(f"{params.item_id} costs {params.price}$.")...

框架特定说明

  1. Django Rest Framework works straight out of the box. Simply add ^{} to your views or use ^{} inside.

  2. For Django without DRF you may need to add the exception handler to ^{}. Qval attempts to do it automatically if ^{} is set. Otherwise you'll see the following message:

    ^{pr 7}$

    Take a look at the plain Django example here

  3. If you are using Flask, you will need to setup exception handlers:

    ^{pr 8}$

    Since ^{} in Flask is a global object, you may want to curry ^{} before usage:

    ^{pr 9}$

    Check out the full Flask exampleexamples/flask-example.py中。

    您可以使用下面的命令运行示例:

    $ PYTHONPATH=. FLASK_APP=examples/flask-example.py flask run
    
  4. Similarly to Flask, with Falcon you will need to setup error handlers:

    ^{pr 11}$

    Full Falcon example可以在这里找到:examples/falcon-example.py

    使用以下命令运行应用程序:

    $ PYTHONPATH=. python examples/falcon-example.py
    

文档

有关详细说明和自动生成的api文档,请参阅documentation。 您还可以查看tests来了解下面的内容是如何工作的。

配置

qval支持通过配置文件和环境变量进行配置。 如果定义了DJANGO_SETTINGS_MODULESETTINGS_MODULE,则将使用指定的配置模块。否则, 所有查找都将在os.environ中完成。

支持的变量:

  • QVAL_MAKE_REQUEST_WRAPPER = myapp.myfile.my_func。自定义make_request()函数的行为, 应用于所有传入请求,然后将结果传递给qval.qval.QueryParamValidator。 提供的函数必须接受request,并返回支持请求接口的对象 (见qval.framework_integration.DummyReqiest)。
    例如,下面的代码将日志记录添加到每个make_request()调用:

    # app/utils.pydefmy_wrapper(f):@functools.wraps(f)defwrapper(request):print(f"Received new request: {request}")returnf(request)returnwrapper

    您还需要在控制台中执行export QVAL_MAKE_REQUEST_WRAPPER=app.utils.my_wrapper 或者将其添加到配置文件中。

  • QVAL_REQUEST_CLASS = path.to.CustomRequestClass@qval()将使用它来确定哪个参数是请求。 如果有实现qval.framework_integration.DummyRequest接口的自定义请求类,请为其提供此变量。

  • QVAL_LOGGERS = [mylogger.factory, ...] | mylogger.factory。路径列表或可调用工厂的路径。 指定的可调用必须返回具有Logger接口的对象。有关详细信息,请参见logging部分。

记录

qval在报告错误时使用名为log的全局对象作为singleton。默认情况下,logging.getLogger 函数用作每次调用的工厂。您可以提供自己的工厂(请参见configuration)或禁用日志记录。错误消息示例:

An error occurred during the validation or inside of the context: exc `<class 'OverflowError'>`((34, 'Numerical result out of range')).
| Parameters: <QueryDict: {'a': ['2.2324'], 'b': ['30000000']}>
| Body      : b''| Exception:
Traceback (most recent call last):
  File "<path>/qval/qval.py", line 338, in inner
    return f(*args, params, **kwargs)
  File "<path>/examples/django-example/app/views.py", line 46, in pow_view
    return JsonResponse({"answer": params.a ** params.b})
OverflowError: (34, 'Numerical result out of range')
Internal Server Error: /api/pow
[19/Nov/2018 07:03:15]"GET /api/pow?a=2.2324&b=30000000 HTTP/1.1"500102

qval导入log对象,并根据需要进行配置:

fromqvalimportlog# For instance, disable logging:log.disable()

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java应该考虑使用DTO来代替Spring控制器层吗?   java为什么要将Maven与Git结合起来?   java试图将CSV转换为XLSX,但使用了错误的逗号拆分列   mysql Spring 3+Hibernate:java。sql。BatchUpdateException:无法添加或更新子行(ManyToMany)   java基本字符串反转器   java无法使用RestControllerAdvice为身份验证失败生成自定义错误消息   java当只允许SQLException时,如何抛出EOFEException?   java如何创建播放模块?   Android中匿名类的java实例化异常问题   java两个停靠组件,其中第二个组件填充剩余空间   java如何在按钮延迟时启用它   Java中正在运行的应用程序中的后台进程   java我正试图从一个字符串打印出这个字符输出   如何使用java socket通过两个不同的wifi连接两台电脑?   javaapachecamel:如何将分层数据从数据库转换为pojo   java Webrtc:OniconConnectionChange和onConnectionChange之间有什么区别   java如何重写已经创建的JTable方法   爪哇扫雷机堆垛机   雅加达ee Java ee EJB 3.0 Glassfish