|
2 | 2 | # -*- coding:utf-8 -*- |
3 | 3 | # __author__ = '__Jack__' |
4 | 4 |
|
5 | | -# from typing import List |
6 | | -# |
7 | | -# from fastapi import Form, File, UploadFile |
8 | | -# from starlette.requests import Request |
9 | | -# |
10 | | -# from fastapi import APIRouter |
11 | | -# |
12 | | -# |
13 | | -# app02 = APIRouter() |
14 | | -# |
15 | | -# |
16 | | -# @app02.post("/user/") |
17 | | -# async def login_post(request: Request, username: str = Form(...), password: str = Form(...)): |
18 | | -# """ |
19 | | -# Form表单操作 |
20 | | -# :param request: |
21 | | -# :param username: |
22 | | -# :param password: |
23 | | -# :return: |
24 | | -# """ |
25 | | -# |
26 | | -# print(f"username: {username}, password: {password}") |
27 | | -# |
28 | | -# return templates.TemplateResponse("post.html", {"request": request, "username": username, "password": password}) |
29 | | -# |
30 | | -# |
31 | | -# @app02.get("/user/") |
32 | | -# async def login_get(request: Request): |
33 | | -# return templates.TemplateResponse("post.html", {"request": request}) |
34 | | -# |
35 | | -# |
36 | | -# @app02.get("/file/") |
37 | | -# async def login_get(request: Request): |
38 | | -# return templates.TemplateResponse("file.html", {"request": request}) |
39 | | -# |
40 | | -# |
41 | | -# @app02.post("/file/") |
42 | | -# async def upload_file(request: Request, files_list: List[bytes] = File(...), files_name: List[UploadFile] = File(...)): |
43 | | -# """ |
44 | | -# 上传多个文件 |
45 | | -# :param request: |
46 | | -# :param files_list: List[bytes]表示可上传多个文件,bytes表示上传一个文件 |
47 | | -# :param files_name: |
48 | | -# :return: |
49 | | -# """ |
50 | | -# |
51 | | -# return templates.TemplateResponse("file.html", { |
52 | | -# "request": Request, |
53 | | -# "file_sizes": [len(file) for file in files_list], # 用字节长度表示文件大小 |
54 | | -# "filenames": [file.filename for file in files_name] |
55 | | -# }) |
56 | | -# |
57 | | -# |
58 | | -# @app02.post("/create_file/") |
59 | | -# async def create_file(request: Request, file1: bytes = File(...), file2: UploadFile = File(...), notes: str = Form(...)): |
60 | | -# """ |
61 | | -# 上传单个文件 |
62 | | -# :param request: |
63 | | -# :param file1: bytes类型可以统计长度,但是没有content_type属性 |
64 | | -# :param file2: UploadFile类有content_type属性,但是不能len()统计文件长度 |
65 | | -# :param notes: |
66 | | -# :return: |
67 | | -# """ |
68 | | -# |
69 | | -# return templates.TemplateResponse("file.html", { |
70 | | -# "request": Request, |
71 | | -# "file_size": len(file1), |
72 | | -# "notes": notes, |
73 | | -# "file2_content_type": file2.content_type |
74 | | -# }) |
| 5 | +from typing import Optional, List |
| 6 | + |
| 7 | +from fastapi import APIRouter, status, Form, File, UploadFile, HTTPException |
| 8 | +from pydantic import BaseModel, EmailStr |
| 9 | + |
| 10 | +app04 = APIRouter() |
| 11 | + |
| 12 | +"""Response Model 响应模型""" |
| 13 | + |
| 14 | + |
| 15 | +class UserIn(BaseModel): |
| 16 | + username: str |
| 17 | + password: str |
| 18 | + email: EmailStr |
| 19 | + mobile: str = "10086" |
| 20 | + address: str = None |
| 21 | + full_name: Optional[str] = None |
| 22 | + |
| 23 | + |
| 24 | +class UserOut(BaseModel): |
| 25 | + username: str |
| 26 | + email: EmailStr # 用 EmailStr 需要 pip install pydantic[email] |
| 27 | + mobile: str = "10086" |
| 28 | + address: str = None |
| 29 | + full_name: Optional[str] = None |
| 30 | + |
| 31 | + |
| 32 | +users = { |
| 33 | + "user01": { "username": "user01", "password": "123123", "email": "[email protected]"}, |
| 34 | + "user02": { "username": "user02", "password": "123456", "email": "[email protected]", "mobile": "110"} |
| 35 | +} |
| 36 | + |
| 37 | + |
| 38 | +@app04.post("/response_model/", response_model=UserOut, response_model_exclude_unset=True) |
| 39 | +async def response_model(user: UserIn): |
| 40 | + """response_model_exclude_unset=True表示默认值不包含在响应中,仅包含实际给的值,如果实际给的值与默认值相同也会包含在响应中""" |
| 41 | + print(user.password) # password不会被返回 |
| 42 | + # return user |
| 43 | + return users["user01"] |
| 44 | + |
| 45 | + |
| 46 | +@app04.post( |
| 47 | + "/response_model/attributes", |
| 48 | + response_model=UserOut, |
| 49 | + # response_model=Union[UserIn, UserOut], |
| 50 | + # response_model=List[UserOut], |
| 51 | + response_model_include=["username", "email", "mobile"], |
| 52 | + response_model_exclude=["mobile"] |
| 53 | +) |
| 54 | +async def response_model_attributes(user: UserIn): |
| 55 | + """response_model_include列出需要在返回结果中包含的字段;response_model_exclude列出需要在返回结果中排除的字段""" |
| 56 | + # del user.password # Union[UserIn, UserOut]后,删除password属性也能返回成功 |
| 57 | + return user |
| 58 | + # return [user, user] |
| 59 | + |
| 60 | + |
| 61 | +"""Response Status Code 响应状态码""" |
| 62 | + |
| 63 | + |
| 64 | +@app04.post("/status_code", status_code=200) |
| 65 | +async def status_code(): |
| 66 | + return {"status_code": 200} |
| 67 | + |
| 68 | + |
| 69 | +@app04.post("/status_attribute", status_code=status.HTTP_200_OK) |
| 70 | +async def status_attribute(): |
| 71 | + print(type(status.HTTP_200_OK)) |
| 72 | + return {"status_code": status.HTTP_200_OK} |
| 73 | + |
| 74 | + |
| 75 | +"""Form Data 表单数据处理""" |
| 76 | + |
| 77 | + |
| 78 | +@app04.post("/login/") |
| 79 | +async def login(username: str = Form(...), password: str = Form(...)): # 定义表单参数 |
| 80 | + """用Form类需要pip install python-multipart; Form类的元数据和校验方法类似Body/Query/Path/Cookie""" |
| 81 | + return {"username": username} |
| 82 | + |
| 83 | + |
| 84 | +"""Request Files 单文件、多文件上传及参数详解""" |
| 85 | + |
| 86 | + |
| 87 | +@app04.post("/file") |
| 88 | +async def file_(file: bytes = File(...)): # 如果要上传多个文件 files: List[bytes] = File(...) |
| 89 | + """使用File类 文件内容会以bytes的形式读入内存 适合于上传小文件""" |
| 90 | + return {"file_size": len(file)} |
| 91 | + |
| 92 | + |
| 93 | +@app04.post("/upload_files") |
| 94 | +async def upload_files(files: List[UploadFile] = File(...)): # 如果要上传单个文件 file: UploadFile = File(...) |
| 95 | + """ |
| 96 | + 使用UploadFile类的优势: |
| 97 | + 1.文件存储在内存中,使用的内存达到阈值后,将被保存在磁盘中 |
| 98 | + 2.适合于图片、视频大文件 |
| 99 | + 3.可以获取上传的文件的元数据,如文件名,创建时间等 |
| 100 | + 4.有文件对象的异步接口 |
| 101 | + 5.上传的文件是Python文件对象,可以使用write(), read(), seek(), close()操作 |
| 102 | + """ |
| 103 | + for file in files: |
| 104 | + contents = await file.read() |
| 105 | + print(contents) |
| 106 | + return {"filename": files[0].filename, "content_type": files[0].content_type} |
| 107 | + |
| 108 | + |
| 109 | +"""【见coronavirus应用】 |
| 110 | +开发COVID-19感染数据查询接口 |
| 111 | +FastAPI项目的静态文件配置 |
| 112 | +Jinja2模板渲染COVID-19查询页面 |
| 113 | +""" |
| 114 | + |
| 115 | +"""Path Operation Configuration 路径操作配置""" |
| 116 | + |
| 117 | + |
| 118 | +@app04.post( |
| 119 | + "/path_operation_configuration", |
| 120 | + response_model=UserOut, |
| 121 | + # tags=["Path", "Operation", "Configuration"], |
| 122 | + summary="This is summary", |
| 123 | + description="This is description", |
| 124 | + response_description="This is response description", |
| 125 | + deprecated=True, |
| 126 | + status_code=status.HTTP_200_OK |
| 127 | +) |
| 128 | +async def path_operation_configuration(user: UserIn): |
| 129 | + """ |
| 130 | + Path Operation Configuration 路径操作配置 |
| 131 | + :param user: 用户信息 |
| 132 | + :return: 返回结果 |
| 133 | + """ |
| 134 | + return user.dict() |
| 135 | + |
| 136 | + |
| 137 | +"""【见run.py】FastAPI 应用的常见配置项""" |
| 138 | + |
| 139 | +"""Handling Errors 错误处理""" |
| 140 | + |
| 141 | + |
| 142 | +@app04.get("/http_exception") |
| 143 | +async def http_exception(city: str): |
| 144 | + if city != "Beijing": |
| 145 | + raise HTTPException(status_code=404, detail="City not found!", headers={"X-Error": "Error"}) |
| 146 | + return {"city": city} |
| 147 | + |
| 148 | + |
| 149 | +@app04.get("/http_exception/{city_id}") |
| 150 | +async def override_http_exception(city_id: int): |
| 151 | + if city_id == 1: |
| 152 | + raise HTTPException(status_code=418, detail="Nope! I don't like 1.") |
| 153 | + return {"city_id": city_id} |
0 commit comments