Pait is an auxiliary framework and it will not change the usage of Web frameworks.
Therefore, before introducing the use of Pait, let's first take a look at the usage of different Web frameworks.
fromflaskimportFlask,Response,jsonify,requestdefdemo_post()->Response:request_dict=request.jsonor{}uid_str:str=request_dict.get("uid","")username:str=request_dict.get("username","")uid=int(uid_str)# Don't think about type conversion exceptions for nowifnot(10<uid<1000):raiseValueError("invalid uid")ifnot(2<=len(username)<=4):raiseValueError("invalid name")# get the corresponding value and return itreturnjsonify({"uid":uid,"username":username})app=Flask("demo")app.add_url_rule("/api","demo",demo_post,methods=["POST"])if__name__=="__main__":app.run(port=8000)
fromstarlette.applicationsimportStarlettefromstarlette.requestsimportRequestfromstarlette.responsesimportJSONResponsefromstarlette.routingimportRouteasyncdefdemo_post(request:Request)->JSONResponse:request_dict=awaitrequest.json()uid_str:str=request_dict.get("uid","")username:str=request_dict.get("username","")uid=int(uid_str)# Don't think about type conversion exceptions for nowifnot(10<uid<1000):raiseValueError("invalid uid")ifnot(2<=len(username)<=4):raiseValueError("invalid name")# get the corresponding value and return itreturnJSONResponse({"uid":uid,"username":username})app=Starlette(routes=[Route("/api",demo_post,methods=["POST"])])if__name__=="__main__":importuvicornuvicorn.run(app)
fromsanic.appimportSanicfromsanic.requestimportRequestfromsanic.responseimportHTTPResponse,jsonasyncdefdemo_post(request:Request)->HTTPResponse:request_dict=awaitrequest.json()uid_str:str=request_dict.get("uid","")username:str=request_dict.get("username","")uid=int(uid_str)# Don't think about type conversion exceptions for nowifnot(10<uid<1000):raiseValueError("invalid uid")ifnot(2<=len(username)<=4):raiseValueError("invalid name")# get the corresponding value and return itreturnjson({"uid":uid,"username":username})app=Sanic(name="demo")app.add_route(demo_post,"/api",methods=["POST"])if__name__=="__main__":importuvicornuvicorn.run(app)
importjsonfromtornado.ioloopimportIOLoopfromtornado.webimportApplication,RequestHandlerclassDemoHandler(RequestHandler):defpost(self)->None:request_dict=json.loads(self.request.body.decode())uid_str:str=request_dict.get("uid","")username:str=request_dict.get("username","")uid=int(uid_str)# Don't think about type conversion exceptions for nowifnot(10<uid<1000):raiseValueError("invalid uid")ifnot(2<=len(username)<=4):raiseValueError("invalid name")# get the corresponding value and return itself.write({"uid":uid,"username":username})app:Application=Application([(r"/api",DemoHandler)])if__name__=="__main__":app.listen(8000)IOLoop.instance().start()
The logic of this sample code is consistent with the sample code on the homepage.
The main feature of the sample code is to register a route into an instance of the Web framework at startup,
and after receiving a request with the URL /api and method POST at runtime, the request will be handed over to the route function for processing.
The logic of the route function is also very simple.
It will verify the data first and return the data only if it meets the requirements. Otherwise, an error will be thrown directly.
Next, we will use Pait in the example code. Their functions are the same, as follows:
The @pait decorator of the first highlighted code in the sample is the core of all functions of Pait.
After using @pait to decorate the route function, Pait will get the function signature through inspect and generate Dependency injection rules.
For example, the parameters of the route function in the second highlighted code are all filled in with key parameters in the format of <name>:<type>=<default>.
Pait automatically transforms key parameters into its own dependency injection rules at initialization time with the following rules:
Key
Meaning
Feature
name
Parameter Name
Pait will use name as the key to get the corresponding value from the requested resource.
type
Parameter Type
Used for parameter verification or conversion
default
Field object of Pait
Different Field types represent obtaining values from different request types; the properties of the Field object tell Pait how to get the value from the request and verify it.
Taking the uid parameter above as an example,
first, Pait will get json data from the request obj.
Second , use uid as the key to get the corresponding value from the json data and convert and verify whether it isint type.
Last, determine whether the value is between 10-1000, if not, an error will be reported directly, if so, it will be assigned to the uid variable.
By comparing the first sample code with the code after using Pait,can see that the code after using Pait is simpler, clearer
and also improves the robustness of the code.
Note
When using Json() , mypy will detect a type mismatch, so you can ignore this problem through Json.i().
If you need mypy to check the values of default, default_factory and example attributes in Json, it is recommended to use Json.t() directly.