from dataclasses import dataclass
from sanic import Sanic, HTTPResponse, Request, json
from sanic.views import HTTPMethodView
from sanic_ext import openapi, validate # type: ignore
app = Sanic(__name__)
@dataclass
class UserListReq:
page: int = 1
page_size: int = 10
@dataclass
class UserCreateReq:
name: str
password: str
class AllUserView(HTTPMethodView):
@openapi.parameter("page", int, required=False)
@openapi.parameter("page_size", int, required=False)
@validate(query=UserListReq)
async def get(self, request: Request, query: UserListReq) -> HTTPResponse:
"""list all user"""
return json(
[
{
'name': 'jack'
},
{
'name': 'tom'
}
]
)
@openapi.body(UserCreateReq, validate=True)
@validate(json=UserCreateReq)
async def post(self, request: Request, body: UserCreateReq) -> HTTPResponse:
"""create user"""
# that is something create user code
return json(None, status=201)
@openapi.body(UserCreateReq, validate=True)
@validate(json=UserCreateReq)
async def create_user(request: Request, body: UserCreateReq):
"""create user"""
# that is something create user code
return json(None, status=201)
@openapi.body({'application/json': UserCreateReq}, validate=True)
@validate(json=UserCreateReq)
async def create_user_json(request: Request, body: UserCreateReq):
"""create user"""
# that is something create user code
return json(None, status=201)
app.add_route(AllUserView.as_view(), '/user_view')
app.add_route(create_user, '/user_func', methods=['POST'])
app.add_route(create_user_json, '/user_func_json', methods=['POST'])
if __name__ == '__main__':
app.run(port=8001)
this is demo code, when I run it
[2022-08-01 22:15:18 +0800] [90880] [INFO] Sanic v22.6.1
[2022-08-01 22:15:18 +0800] [90880] [INFO] Goin' Fast @ http://127.0.0.1:8001
[2022-08-01 22:15:18 +0800] [90880] [INFO] mode: production, single worker
[2022-08-01 22:15:18 +0800] [90880] [INFO] server: sanic, HTTP/1.1
[2022-08-01 22:15:18 +0800] [90880] [INFO] python: 3.10.0
[2022-08-01 22:15:18 +0800] [90880] [INFO] platform: macOS-12.4-arm64-arm-64bit
[2022-08-01 22:15:18 +0800] [90880] [INFO] packages: sanic-routing==22.3.0, sanic-ext==22.6.2
[2022-08-01 22:15:18 +0800] [90880] [INFO] Sanic Extensions:
[2022-08-01 22:15:18 +0800] [90880] [INFO] > templating [jinja2==3.0.3]
[2022-08-01 22:15:18 +0800] [90880] [INFO] > http
[2022-08-01 22:15:18 +0800] [90880] [INFO] > openapi [http://127.0.0.1:8001/docs]
[2022-08-01 22:15:18 +0800] [90880] [INFO] > injection [0 added]
[2022-08-01 22:15:18 +0800] [90880] [INFO] Starting worker [90880]
In this code, it register three routes:
/user_view
/user_func
/user_func_json
when I use curl to request these url:
- /user_view
curl -X 'POST' \
'http://127.0.0.1:8001/user_view' \
-H 'accept: */*' \
-H 'Content-Type: */*' \
-d '{
"name": "andy",
"password": "123456"
}'
[2022-08-01 22:26:24 +0800] [90880] [ERROR] Exception occurred while handling uri: 'http://127.0.0.1:8001/user_view'
Traceback (most recent call last):
File "handle_request", line 83, in handle_request
from sanic.models.handler_types import ListenerType, MiddlewareType
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/sanic_ext/extensions/openapi/openapi.py", line 202, in handler
data = request.json
AttributeError: 'AllUserView' object has no attribute 'json'
[2022-08-01 22:26:24 +0800] - (sanic.access)[INFO][127.0.0.1:60582]: POST http://127.0.0.1:8001/user_view 500 139
- /user_func
curl -X 'POST' \
'http://127.0.0.1:8001/user_func' \
-H 'accept: */*' \
-H 'Content-Type: */*' \
-d '{
"name": "andy",
"password": "123456"
}'
[2022-08-01 22:28:24 +0800] - (sanic.access)[INFO][127.0.0.1:60669]: POST http://127.0.0.1:8001/user_func 201 4
- /user_func_json
curl -X 'POST' \
'http://127.0.0.1:8001/user_func_json' \
-H 'accept: */*' \
-H 'Content-Type: application/json' \
-d '{
"name": "andy",
"password": "123456"
}'
[2022-08-01 22:30:35 +0800] - (sanic.access)[INFO][127.0.0.1:60753]: POST http://127.0.0.1:8001/user_func_json 400 84
[2022-08-01 22:30:35 +0800] [90880] [ERROR] Exception occurred while handling uri: 'http://127.0.0.1:8001/user_func_json'
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/sanic_ext/extras/validation/setup.py", line 38, in do_validation
validation = model(
TypeError: 'dict' object is not callable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "handle_request", line 83, in handle_request
from sanic.models.handler_types import ListenerType, MiddlewareType
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/sanic_ext/extensions/openapi/openapi.py", line 210, in handler
await do_validation(
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/sanic_ext/extras/validation/setup.py", line 44, in do_validation
raise ValidationError(e)
sanic_ext.exceptions.ValidationError: 'dict' object is not callable
Why do the responses of these three requests have these differences?