Simple Python Schema


Python Schema instructions

Project Address: GitHub

1. Schema What is that?

No matter what we do apply, as long as the user input and dealing with, there is a principle - never trust user input data. Means that we have to be rigorous validation of user input, general input data is sent to the web development backend API in JSON form, API to do validation of input data. I usually add a lot of judgment, all kinds of if, resulting in code is very ugly, can not there is a more elegant way of verifying user data it? Schema comes in handy.

Schema is very simple, it's a few hundred lines of code, it is a core class: Schema.

2. Install

pip install schema

1. afferent to Schema types (int, str, float, etc.)

E.g:

from schema import Schema

Schema(int).validate(10)
# 10
Schema(int).validate('10')
# SchemaUnexpectedTypeError: '10' should be instance of 'int'

Schema validation will be seen to validate the method passed in object type is not specified, is the incoming data is returned, otherwise thrown a SchemaError of (SchemaUnexpectedTypeError is a subclass of SchemaError).

2. Schema to the incoming object class (function with the __call__ etc.) can be called

E.g:

Schema(lambda x: 0<x<10).validate(5)
# 5
Schema(lambda x: 0<x<10).validate(57)
# SchemaError: <lambda>(57) should evaluate to True

Custom Functions:

def secre_validate(password):
    password_list = ["123456", "666666", "888888", "abcdef", "aaaaaa", "112233"]
    if password in password_list:
        return False
    return True

Schema(secre_validate,  error="字符串已经存在").validate("123456")

# schema.SchemaError: 字符串已经存在

Schema validate method will be seen the value passed to the corresponding function inside passed as parameters, the function returns a value of True if the input data is returned, otherwise an exception is thrown.

3. Schema class to validate the incoming object with the method

Schema is also built a number of classes (Use, And, Or, etc.), are examples of these classes with a validate method also passed as a parameter of the Schema, for example:

from schema import Schema, And

# And代表两个条件必须同时满足
Schema(And(str, lambda s: len(s) > 2)).validate('abcd')
# 'abcd'

4. Schema afferent to the container objects (list, tuple, set, etc.)

E.g:

Schema([int, float]).validate([1, 2, 3, 4.0])
# [1, 2, 3, 4.0]

It corresponds, for [1, 2, 3, 4.0] of any element which must be int or float the job (or the relationship between the note)

5. Schema to pass in a dictionary object (most of the scenes are passed using Schema dictionary object, this is very important)

Schema({'name': str, 'age': int}).validate({'name': 'foobar', 'age': 18})
# {'age': 18, 'name': 'foobar'}
Schema({'name': str, 'age': int}).validate({'name': 'foobar'})
# SchemaMissingKeyError: Missing keys: 'age'

First of all, a clear two concepts, Schema incoming class dictionary, called mode dictionary, valdiate incoming method called dictionary data dictionary.

First, Schema will determine whether the pattern dictionary and data dictionary key exactly the same, not the same thing directly thrown. If you like to get the data dictionary to verify the value of the corresponding value mode dictionary, only to return all data if the data dictionary value can be verified through it, otherwise throw an exception, is not feeling this sudden feeling fresh verification of it?

6. faqs

6.1 Schema Incoming dictionary is very handy, but some of my data is optional, that some key may not provide how to do?

from schema import Optional, Schema


Schema({'name': str, Optional('age'): int}).validate({'name': 'foobar'})
# {'name': 'foobar'}
Schema({'name': str, Optional('age', default=18): int}).validate({'name': 'foobar'})
# {'age': 18, 'name': 'foobar'}

6.2 prohibited from entering a key: Forbidden

Forbidden a key may be prohibited:

from schema import Schema, Forbidden

Schema({Forbidden('name'): str, 'age': int}).validate({"age": 15})                            # {"age": 15}
Schema({Forbidden('name'): str, 'age': int}).validate({"name": "laozhang", "age": 15})        # schema.SchemaForbiddenKeyError
Schema({Forbidden('name'): str, 'age': int}).validate({"name": 10, "age": 15})                # schema.SchemaWrongKeyError

It is worth noting that, paired with disabled secret key value will determine whether it will be rejected:

from schema import Schema, Forbidden

Schema({Forbidden('name'): int, 'name': str}).validate({'name': 'laozhang'})                  # {'name': 'laozhang'}
Schema({Forbidden('name'): str, 'name': str}).validate({'name': 'laozhang'})                  # schema.SchemaForbiddenKeyError

In addition, Forbidden priority higher than Optional:

from schema import Schema, Forbidden, Optional

Schema({Forbidden('name'): str, Optional('name'): str}).validate({"name": "laozhang"})        # schema.SchemaForb

I want only 6.3 Schema validation part of the incoming data dictionary, you can have extra key but do not Baocuo, how do?

Schema({'name': str, 'age': int}, ignore_extra_keys=True).validate({'name': 'foobar', 'age': 100, 'sex': 'male'})
# {'age': 100, 'name': 'foobar'}

6.4 Schema thrown exception information is not very friendly, and I want to customize error messages, how to do?

Schema own class (Use, And, Or, Regex, Schema, etc.) has a parameter error, an error message can be customized

Schema({'name': str, 'age': Use(int, error='年龄必须是整数')}).validate({'name': 'foobar', 'age': 'abc'})
# SchemaError: 年龄必须是整数

6.5 Use

Use at the time of verification, it will automatically help you convert its value

from schema import Schema, Use

print Schema(Use(int)).validate(10)                 # 10-->int类型
print Schema(Use(int)).validate('10')               # 10-->int类型
print Schema(Use(int)).validate('xiaoming')         # schema.SchemaError

6.6 Const

We know that at the time of verification of Use, will automatically help you convert its value. Const be leaving the original untouched:

from schema import Schema, Use, Const

print Schema(Const(Use(int))).validate('10')        # 10-->str类型

7. A more complex example:

from schema import Schema, And, Optional, SchemaError, Regex


def name_check(name):
    password_list = ["root", "admin", "888888", "baba", "aaaaaa", "112233"]
    if name in password_list:
        return False
    return True


schema = {
    "id": And(int, lambda x: 100 <= x, error="id必须是整数,大于等于100"),
    "name": And(str, name_check, error="name已经存在"),
    "price": And(float, lambda x: 111 > x > 0, error="price必须是大于0小于111的小数"),
    "data": {
        "password": And(Regex("[a-z0-9A-Z]{8,20}"), error="密码为数字、字母,长度8-20"),
        "email": And(Regex("^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"), error="email格式错误")
    },
    Optional("info", default="这个key可以不提供,我设置了这一段默认值。"): str,
}

data = {
    "id": 111,
    "name": "jarvis",
    "price": 9.5,
    "data": {
        "password": "222agfwetAAA",
        "email": "[email protected]",
    }
}

try:
    a = Schema(schema).validate(data)
except SchemaError as e:
    print(e)
else:
    print("验证成功!\n{}".format(a))


# 验证成功!
# {'id': 111, 'name': 'jarvis', 'price': 9.5, 'data': {'password': '222agfwetAAA', 'email': '[email protected]'}, 'info': '这个key可以不提供,我设置了这一段默认值。'}

Reference article: https: //segmentfault.com/a/1190000011777230#articleHeader5

Guess you like

Origin www.cnblogs.com/ChangAn223/p/11239537.html