├── .gitattributes ├── FastAPI_NO.36_None └── None.txt ├── FastAPI_NO.37_None └── None.txt ├── FastAPI_NO.38_full-stack └── FastAPI_NO.38.zip ├── FastAPI_NO.39_None └── None.txt ├── FastAPI_NO.40_None └── None.txt ├── FastAPI_NO.41_None └── None.txt ├── FastAPI_NO.42_None └── None.txt ├── FastAPI_NO.43_后续:修正 └── NO.43_后续:修正.txt ├── FastAPI_NO.44_full_stack_helloworld ├── FastAPI_No.2_helloworld.py └── hello-world.zip ├── FastAPI_NO.45_None └── None.txt ├── FastAPI_NO.46_None └── None.txt ├── FastAPI_NO.47_None └── None.txt ├── FastAPI_NO.48_OneHtmlFile_full-stack-helloworld ├── FastAPI_helloworld.py └── index.html ├── FastAPI_No.10_Query_Parameters_and_String_Validations └── FastAPI_No.10_Query_Parameters_and_String_Validations.py ├── FastAPI_No.11_Path_Parameters_and_Numeric_Validations └── FastAPI_No.11_Path_Parameters_and_Numeric_Validations.py ├── FastAPI_No.12_Body_Multiple_Parameters ├── FastAPI_No.12_Body_Multiple_Parameters_1.py ├── FastAPI_No.12_Body_Multiple_Parameters_2.py ├── FastAPI_No.12_Body_Multiple_Parameters_3.py └── FastAPI_No.12_Body_Multiple_Parameters_4.py ├── FastAPI_No.13_Body_Fields ├── FastAPI_No.13_Body_Fields_1.py └── FastAPI_No.13_Body_Fields_2.py ├── FastAPI_No.14_Body_Nested_Models ├── FastAPI_No.14_Body_Nested_Models_1.py ├── FastAPI_No.14_Body_Nested_Models_2.py └── FastAPI_No.14_Body_Nested_Models_3.py ├── FastAPI_No.15_Extra_data_types ├── FastAPI_No.15_Extra_data_types_1.py └── FastAPI_No.15_Extra_data_types_2.py ├── FastAPI_No.16_Cookie_Parameters └── FastAPI_No.16_Cookie_Parameters.py ├── FastAPI_No.17_Header_Parameters └── FastAPI_No.17_Header_Parameters.py ├── FastAPI_No.18_Response_Model ├── FastAPI_No.18_Response_Model_1.py ├── FastAPI_No.18_Response_Model_2.py ├── FastAPI_No.18_Response_Model_3.py ├── FastAPI_No.18_Response_Model_4.py └── 注意可能需要安装这个.png ├── FastAPI_No.19_Extra_Model ├── FastAPI_No.19_Extra_Model_1.py ├── FastAPI_No.19_Extra_Model_2.py ├── FastAPI_No.19_Extra_Model_3.py ├── FastAPI_No.19_Extra_Model_4.py └── FastAPI_No.19_Extra_Model_5.py ├── FastAPI_No.1_介绍 └── 相关网址.txt ├── FastAPI_No.20.1_Handling_Errors ├── FastAPI_No.20.1_Handling_Errors_1.py ├── FastAPI_No.20.1_Handling_Errors_2.py ├── FastAPI_No.20.1_Handling_Errors_3.py ├── FastAPI_No.20.1_Handling_Errors_4.py └── FastAPI_No.20.1_Handling_Errors_5.py ├── FastAPI_No.20_Response_Status_Code └── FastAPI_No.20_Response_Status.py ├── FastAPI_No.21_Form_Data ├── FastAPI_No.21_Form_Data.py └── templates │ └── post.html ├── FastAPI_No.22_Request_Files ├── FastAPI_No.22_Request_Files.py └── templates │ └── post.html ├── FastAPI_No.23_Request_Forms_and_Files ├── FastAPI_No.23_Request_Forms_and_Files.py └── templates │ └── post.html ├── FastAPI_No.24_JSON_Compatible_Encoder └── FastAPI_No.24_JSON_Compatible_Encoder.py ├── FastAPI_No.25_Body_updates ├── FastAPI_No.25_Body_updates_1.py └── FastAPI_No.25_Body_updates_2.py ├── FastAPI_No.26_Dependencies ├── FastAPI_No.26_Dependencies_1.py ├── FastAPI_No.26_Dependencies_2.py ├── FastAPI_No.26_Dependencies_3.py └── FastAPI_No.26_Dependencies_4.py ├── FastAPI_No.27_Security ├── 1.jpg ├── FastAPI_No.27_Security_1.py ├── FastAPI_No.27_Security_2.py ├── FastAPI_No.27_Security_3.py ├── FastAPI_No.27_Security_4.py └── test_1.py ├── FastAPI_No.28_Middleware+CORS ├── CORS.jpg ├── FastAPI_No.28_CORS.py ├── FastAPI_No.28_Middleware.py ├── FastAPI_No.2_helloworld.py ├── Middleware.jpg ├── static │ └── jquery.min.js └── templates │ └── index.html ├── FastAPI_No.29_SQLDatabases ├── 1_ORM.jpg ├── 2_Sqlalchemy.jpg ├── 3_yield.jpg ├── FastAPI_No.29_SQLDatabases │ ├── __init__.py │ ├── sql_app │ │ ├── __init__.py │ │ ├── alt_main.py │ │ ├── crud.py │ │ ├── database.py │ │ ├── main.py │ │ ├── models.py │ │ └── schemas.py │ └── test.db ├── test_0 │ ├── NO.1_yield.py │ ├── NO.2_db.py │ └── db_test_1.db └── test_1 │ ├── db_test_1.py │ └── db_test_3.db ├── FastAPI_No.2_helloworld ├── FastAPI_No.1_helloworld.py ├── FastAPI_No.2_helloworld.py ├── __pycache__ │ └── main.cpython-37.pyc └── main.py ├── FastAPI_No.30_Bigger_Applications_Multiple_Files └── app │ ├── main.py │ └── routers │ ├── __pycache__ │ ├── items.cpython-37.pyc │ └── users.cpython-37.pyc │ ├── items.py │ └── users.py ├── FastAPI_No.31_Background_Tasks ├── FastAPI_No.31_Background_Tasks.py └── log.txt ├── FastAPI_No.32_Application_Configuration └── FastAPI_No.32_Application_Configuration.py ├── FastAPI_No.33_Static_Files ├── FastAPI_No.33_Static_Files.py ├── static │ ├── css │ │ ├── bootstrap.min.css │ │ ├── jumbotron.css │ │ └── signin.css │ ├── imgs │ │ └── favicon.ico │ └── js │ │ ├── bootstrap.min.js │ │ └── jquery.min.js └── templates │ └── index.html ├── FastAPI_No.34_Testing ├── __init__.py ├── main.py ├── main_b.py ├── test_main.py └── test_main_b.py ├── FastAPI_No.35_Debugging └── FastAPI_No.35_Debugging.py ├── FastAPI_No.3_templates ├── FastAPI_No.2_templates.py └── templates │ └── index.html ├── FastAPI_No.4_form ├── post_test_5.py └── templates │ ├── index.html │ └── post.html ├── FastAPI_No.5_file ├── post_test_5.py └── templates │ ├── index.html │ └── post.html ├── FastAPI_No.6_bootstrap_static ├── post_test_5.py ├── static │ ├── css │ │ ├── bootstrap.min.css │ │ ├── jumbotron.css │ │ └── signin.css │ ├── imgs │ │ └── favicon.ico │ └── js │ │ ├── bootstrap.min.js │ │ └── jquery.min.js └── templates │ ├── index.html │ └── signin.html ├── FastAPI_No.7_Path_Parameters ├── FastAPI_No.7_Path_Parameters_1.py └── FastAPI_No.7_Path_Parameters_2.py ├── FastAPI_No.8_Query_Parameters └── FastAPI_No.8_Query_Parameters.py ├── FastAPI_No.9_Request_Body └── FastAPI_No.9_Request_Body.py ├── README.md └── win_from_import_err.zip /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=python 2 | *.css linguist-language=python 3 | *.html linguist-language=python 4 | -------------------------------------------------------------------------------- /FastAPI_NO.36_None/None.txt: -------------------------------------------------------------------------------- 1 | None -------------------------------------------------------------------------------- /FastAPI_NO.37_None/None.txt: -------------------------------------------------------------------------------- 1 | None -------------------------------------------------------------------------------- /FastAPI_NO.38_full-stack/FastAPI_NO.38.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_NO.38_full-stack/FastAPI_NO.38.zip -------------------------------------------------------------------------------- /FastAPI_NO.39_None/None.txt: -------------------------------------------------------------------------------- 1 | None -------------------------------------------------------------------------------- /FastAPI_NO.40_None/None.txt: -------------------------------------------------------------------------------- 1 | None -------------------------------------------------------------------------------- /FastAPI_NO.41_None/None.txt: -------------------------------------------------------------------------------- 1 | None -------------------------------------------------------------------------------- /FastAPI_NO.42_None/None.txt: -------------------------------------------------------------------------------- 1 | None -------------------------------------------------------------------------------- /FastAPI_NO.43_后续:修正/NO.43_后续:修正.txt: -------------------------------------------------------------------------------- 1 | 后续修复: 2 | 1、后端修改: 3 | uvicorn.run(app,host='0.0.0.0',port=8888) 4 | 2、前端.env文件修改: 5 | VUE_APP_NAME=FastAPI 6 | VUE_APP_DOMAIN_DEV=192.168.1.101:8888 7 | (这里的192.168.1.101是本机局域网IP地址,FastAPI是希望显示的title) 8 | 3、nginx的nginx.conf修改: 9 | listen 80; 10 | server_name 192.168.1.101; 11 | 4、前端使用nodejs进行npm run build(或cnpm run build)打包。 12 | 5、删掉原来nginx里面的dist文件夹,并且拷贝刚打包的dist文件夹。 13 | 6、重启nginx和后端FastAPI 14 | 达到效果: 15 | 1、页面标题正常显示标题 16 | 2、局域网内其它电脑或手机可以正常访问和登录 -------------------------------------------------------------------------------- /FastAPI_NO.44_full_stack_helloworld/FastAPI_No.2_helloworld.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI,Body,Form 3 | from starlette.middleware.cors import CORSMiddleware 4 | from pydantic import BaseModel 5 | 6 | app = FastAPI() 7 | 8 | 9 | app.add_middleware( # 添加中间件 10 | CORSMiddleware, # CORS中间件类 11 | allow_origins=["*"], # 允许起源 12 | allow_credentials=True, # 允许凭据 13 | allow_methods=["*"], # 允许方法 14 | allow_headers=["*"], # 允许头部 15 | ) 16 | 17 | 18 | @app.get("/") 19 | async def main(): 20 | return {"message": "Hello FastAPI, from get..."} 21 | 22 | @app.get("/{a}") 23 | async def regist(a): 24 | print('前端数据是:',a) 25 | print(type(a)) 26 | return a 27 | 28 | 29 | if __name__ == '__main__': 30 | import uvicorn 31 | uvicorn.run(app, host="0.0.0.0", port=8888) 32 | 33 | -------------------------------------------------------------------------------- /FastAPI_NO.44_full_stack_helloworld/hello-world.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_NO.44_full_stack_helloworld/hello-world.zip -------------------------------------------------------------------------------- /FastAPI_NO.45_None/None.txt: -------------------------------------------------------------------------------- 1 | None -------------------------------------------------------------------------------- /FastAPI_NO.46_None/None.txt: -------------------------------------------------------------------------------- 1 | None -------------------------------------------------------------------------------- /FastAPI_NO.47_None/None.txt: -------------------------------------------------------------------------------- 1 | None -------------------------------------------------------------------------------- /FastAPI_NO.48_OneHtmlFile_full-stack-helloworld/FastAPI_helloworld.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from starlette.middleware.cors import CORSMiddleware 4 | 5 | app = FastAPI() 6 | 7 | 8 | app.add_middleware( # 添加中间件 9 | CORSMiddleware, # CORS中间件类 10 | allow_origins=["*"], # 允许起源 11 | allow_credentials=True, # 允许凭据 12 | allow_methods=["*"], # 允许方法 13 | allow_headers=["*"], # 允许头部 14 | ) 15 | 16 | 17 | @app.get("/") 18 | async def main(): 19 | return {"message": "Hello , this is FastAPI."} 20 | 21 | @app.get("/{a}") 22 | async def regist(a): 23 | print('前端数据是:',a) 24 | # print(type(a)) 25 | return a 26 | 27 | 28 | if __name__ == '__main__': 29 | import uvicorn 30 | uvicorn.run(app, host="0.0.0.0", port=8888) 31 | 32 | -------------------------------------------------------------------------------- /FastAPI_NO.48_OneHtmlFile_full-stack-helloworld/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Vue + FastAPI 演示前后端分离

13 |
14 | 请输入后端IP: 15 | 16 |
17 | 请输入发送内容: 18 | 19 |

20 | 21 |
22 | 接收到后端数据:{{ getdata }} 23 |
24 | 25 | 54 | 55 | 58 | 59 | -------------------------------------------------------------------------------- /FastAPI_No.10_Query_Parameters_and_String_Validations/FastAPI_No.10_Query_Parameters_and_String_Validations.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI, Query 3 | from typing import List 4 | 5 | app = FastAPI() 6 | ######################################################### 7 | # 限制长度 8 | @app.get("/items/") 9 | async def read_items(q: str = Query(..., min_length=3, max_length=50)): 10 | #填None就是默认值 填 ...则是必填项 11 | results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} 12 | if q: 13 | results.update({"q": q}) 14 | return results 15 | ######################################################### 16 | #正则表达式 17 | @app.get("/items2/") 18 | async def read_items2( 19 | q: str = Query(None, min_length=3, max_length=50, regex="^nice") 20 | ): 21 | results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} 22 | if q: 23 | results.update({"q": q}) 24 | return results 25 | ######################################################### 26 | #列表 27 | @app.get("/items3/") 28 | async def read_items3(q: List[str] = Query(["foo", "bar"])): 29 | query_items = {"q": q} 30 | return query_items 31 | ######################################################### 32 | #别名参数 33 | @app.get("/items4/") 34 | async def read_items4(q: str = Query(None, alias="item-query")): 35 | results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} 36 | if q: 37 | results.update({"q": q}) 38 | return results 39 | ######################################################### 40 | #弃用参数 41 | @app.get("/items5/") 42 | async def read_items5( 43 | q: str = Query( 44 | None, 45 | alias="item-query", 46 | title="Query string", 47 | description="Query string for the items to search in the database that have a good match", 48 | min_length=3, 49 | max_length=50, 50 | regex="^fixedquery$", 51 | deprecated=True, 52 | ) 53 | ): 54 | results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} 55 | if q: 56 | results.update({"q": q}) 57 | return results 58 | ######################################################### 59 | 60 | 61 | 62 | if __name__ == '__main__': 63 | import uvicorn 64 | uvicorn.run(app, host="127.0.0.1", port=8000) 65 | 66 | -------------------------------------------------------------------------------- /FastAPI_No.11_Path_Parameters_and_Numeric_Validations/FastAPI_No.11_Path_Parameters_and_Numeric_Validations.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI, Path, Query 3 | 4 | app = FastAPI() 5 | 6 | 7 | @app.get("/items/{item_id}") 8 | async def read_items( 9 | item_id: int = Path(..., title="The ID of the item to get", ge=50, le=100),#ge 大于等于 gt是大于 le是小于等于 10 | q: str = Query(None, alias="item-query"), 11 | size: float = Query(1, gt=0, lt=10.5) 12 | ): 13 | results = {"item_id": item_id} 14 | if q: 15 | results.update({"q": q}) 16 | return results 17 | 18 | 19 | 20 | if __name__ == '__main__': 21 | import uvicorn 22 | uvicorn.run(app, host="127.0.0.1", port=8000) 23 | 24 | -------------------------------------------------------------------------------- /FastAPI_No.12_Body_Multiple_Parameters/FastAPI_No.12_Body_Multiple_Parameters_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI, Path 3 | from pydantic import BaseModel 4 | 5 | app = FastAPI() 6 | 7 | 8 | class Item(BaseModel): 9 | name: str 10 | description: str = None 11 | price: float 12 | tax: float = None 13 | 14 | # 混合参数 15 | @app.put("/items/{item_id}") 16 | async def update_item( 17 | *, 18 | item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000), 19 | q: str = None, 20 | item: Item = None, 21 | ): 22 | results = {"item_id": item_id} 23 | if q: 24 | results.update({"q": q}) 25 | if item: 26 | results.update({"item": item}) 27 | return results 28 | 29 | 30 | if __name__ == '__main__': 31 | import uvicorn 32 | uvicorn.run(app, host="127.0.0.1", port=8000) 33 | 34 | -------------------------------------------------------------------------------- /FastAPI_No.12_Body_Multiple_Parameters/FastAPI_No.12_Body_Multiple_Parameters_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Body, FastAPI 3 | from pydantic import BaseModel 4 | 5 | app = FastAPI() 6 | 7 | 8 | class Item(BaseModel): 9 | name: str 10 | description: str = None 11 | price: float 12 | tax: float = None 13 | 14 | 15 | class User(BaseModel): 16 | username: str 17 | full_name: str = None 18 | 19 | # body的奇异值 20 | @app.put("/items/{item_id}") 21 | async def update_item( 22 | *, item_id: int, item: Item, user: User, importance: int = Body(...) 23 | ): 24 | results = {"item_id": item_id, "item": item, "user": user, "importance": importance} 25 | return results 26 | 27 | 28 | 29 | if __name__ == '__main__': 30 | import uvicorn 31 | uvicorn.run(app, host="127.0.0.1", port=8000) 32 | 33 | -------------------------------------------------------------------------------- /FastAPI_No.12_Body_Multiple_Parameters/FastAPI_No.12_Body_Multiple_Parameters_3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Body, FastAPI 3 | from pydantic import BaseModel 4 | 5 | app = FastAPI() 6 | 7 | 8 | class Item(BaseModel): 9 | name: str 10 | description: str = None 11 | price: float 12 | tax: float = None 13 | 14 | #嵌入一个单body的参数 15 | @app.put("/items/{item_id}") 16 | async def update_item(*, item_id: int, item: Item = Body(..., embed=True)): 17 | results = {"item_id": item_id, "item": item} 18 | return results 19 | 20 | 21 | 22 | if __name__ == '__main__': 23 | import uvicorn 24 | uvicorn.run(app, host="127.0.0.1", port=8000) 25 | 26 | -------------------------------------------------------------------------------- /FastAPI_No.12_Body_Multiple_Parameters/FastAPI_No.12_Body_Multiple_Parameters_4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Body, FastAPI 3 | from pydantic import BaseModel 4 | 5 | app = FastAPI() 6 | 7 | 8 | class Item(BaseModel): 9 | name: str 10 | description: str = None 11 | price: float 12 | tax: float = None 13 | 14 | 15 | class User(BaseModel): 16 | username: str 17 | full_name: str = None 18 | 19 | # 多主体参数和查询 20 | @app.put("/items/{item_id}") 21 | async def update_item( 22 | *, 23 | item_id: int, 24 | item: Item, 25 | user: User, 26 | importance: int = Body(..., gt=0), 27 | q: str = None 28 | ): 29 | results = {"item_id": item_id, "item": item, "user": user, "importance": importance} 30 | if q: 31 | results.update({"q": q}) 32 | return results 33 | 34 | 35 | 36 | if __name__ == '__main__': 37 | import uvicorn 38 | uvicorn.run(app, host="127.0.0.1", port=8000) 39 | 40 | -------------------------------------------------------------------------------- /FastAPI_No.13_Body_Fields/FastAPI_No.13_Body_Fields_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Body, FastAPI 3 | from pydantic import BaseModel, Field 4 | 5 | app = FastAPI() 6 | 7 | 8 | class Item(BaseModel): 9 | name: str 10 | description: str = Field(None, title="The description of the item", max_length=6) 11 | price: float = Field(..., gt=0, description="The price must be greater than zero") 12 | tax: float = None 13 | 14 | 15 | @app.put("/items/{item_id}") 16 | async def update_item(*, item_id: int, item: Item = Body(..., embed=True)): 17 | results = {"item_id": item_id, "item": item} 18 | return results 19 | 20 | if __name__ == '__main__': 21 | import uvicorn 22 | uvicorn.run(app, host="127.0.0.1", port=8000) 23 | 24 | -------------------------------------------------------------------------------- /FastAPI_No.13_Body_Fields/FastAPI_No.13_Body_Fields_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Body, FastAPI 3 | from pydantic import BaseModel, Field 4 | 5 | app = FastAPI() 6 | 7 | 8 | class Item(BaseModel): 9 | name: str 10 | description: str = None 11 | price: float = Field(..., gt=0) 12 | tax: float = None 13 | 14 | 15 | @app.put("/items/{item_id}") 16 | async def update_item( 17 | *, 18 | item_id: int, 19 | item: Item = Body(..., 20 | example={ # example是Body里没有的字段;不会添加任何验证,而只会添加注释;不是example也不行 21 | "name": "Foo", 22 | "description": "A very nice Item", 23 | "price": 0, 24 | "toooo": 3.2, 25 | # "toooooooooo": 3.2, # 超过的键值对,会全部显示原来的Item 26 | }, 27 | ) 28 | ): 29 | results = {"item_id": item_id, "item": item} 30 | return results 31 | 32 | 33 | if __name__ == '__main__': 34 | import uvicorn 35 | uvicorn.run(app, host="127.0.0.1", port=8000) 36 | 37 | -------------------------------------------------------------------------------- /FastAPI_No.14_Body_Nested_Models/FastAPI_No.14_Body_Nested_Models_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import List, Set 3 | from fastapi import FastAPI 4 | from pydantic import BaseModel 5 | 6 | app = FastAPI() 7 | 8 | 9 | class Item(BaseModel): 10 | name: str 11 | description: str = None 12 | price: float 13 | tax: float = None 14 | tags0: list = [] 15 | tags1: List[str] = [] 16 | tags2: Set[str] = set() 17 | 18 | 19 | @app.put("/items/{item_id}") 20 | async def update_item(*, item_id: int, item: Item): 21 | results = {"item_id": item_id, "item": item} 22 | return results 23 | 24 | 25 | if __name__ == '__main__': 26 | import uvicorn 27 | uvicorn.run(app, host="127.0.0.1", port=8000) 28 | 29 | -------------------------------------------------------------------------------- /FastAPI_No.14_Body_Nested_Models/FastAPI_No.14_Body_Nested_Models_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import Set,List 3 | from fastapi import FastAPI 4 | from pydantic import BaseModel 5 | 6 | app = FastAPI() 7 | 8 | 9 | class Image(BaseModel): 10 | url: str 11 | name: str 12 | 13 | 14 | class Item(BaseModel): 15 | name: str 16 | description: str = None 17 | price: float 18 | tax: float = None 19 | tags: Set[str] = set() # 集合 创建一个空集合必须用 set() 而不是 { } 20 | image: Image = None # 使用子模型作为类型 21 | images: List[Image] = None # 带有子模型列表的属性 22 | 23 | 24 | # 到处都有编辑器支持 25 | @app.put("/items/{item_id}") 26 | async def update_item(*, item_id: int, item: Item): 27 | results = {"item_id": item_id, "item": item} 28 | return results 29 | 30 | 31 | 32 | if __name__ == '__main__': 33 | import uvicorn 34 | uvicorn.run(app, host="127.0.0.1", port=8000) 35 | 36 | -------------------------------------------------------------------------------- /FastAPI_No.14_Body_Nested_Models/FastAPI_No.14_Body_Nested_Models_3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import List, Dict 3 | 4 | from fastapi import FastAPI 5 | from pydantic import BaseModel, HttpUrl 6 | 7 | app = FastAPI() 8 | 9 | 10 | class Image(BaseModel): 11 | url: HttpUrl # 该字符串将被检查为有效的URL,并在JSON Schema / OpenAPI中进行记录。 12 | # 特殊类型和验证 https://pydantic-docs.helpmanual.io/usage/types/ 13 | name: str 14 | 15 | # 纯列表体 16 | @app.post("/images/multiple/") 17 | async def create_multiple_images(*, images: List[Image]): 18 | return images 19 | 20 | # 任意dicts (无需事先知道有效的字段/属性名称是什么)(如果您想接收未知的密钥,这将很有用。) 21 | @app.post("/index-weights/") 22 | async def create_index_weights(weights: Dict[int, float]): 23 | return weights 24 | 25 | 26 | 27 | if __name__ == '__main__': 28 | import uvicorn 29 | uvicorn.run(app, host="127.0.0.1", port=8000) 30 | 31 | -------------------------------------------------------------------------------- /FastAPI_No.15_Extra_data_types/FastAPI_No.15_Extra_data_types_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from datetime import datetime, time, timedelta 3 | from uuid import UUID 4 | from uuid import uuid1 5 | from fastapi import Body, FastAPI 6 | 7 | app = FastAPI() 8 | 9 | # class Item(BaseModel): 10 | # xxx: UUID 11 | # ... 12 | 13 | # 额外数据类型 14 | # https://fastapi.tiangolo.com/tutorial/extra-data-types/ 15 | @app.put("/items/{item_id}") 16 | async def read_items( 17 | item_id: UUID , 18 | start_datetime: datetime = Body(None), 19 | end_datetime: datetime = Body(None), 20 | repeat_at: time = Body(None), 21 | process_after: timedelta = Body(None), 22 | ): 23 | start_process = start_datetime + process_after 24 | duration = end_datetime - start_process 25 | return { 26 | "item_id": item_id, 27 | "start_datetime": start_datetime, 28 | "end_datetime": end_datetime, 29 | "repeat_at": repeat_at, 30 | "process_after": process_after, 31 | "start_process": start_process, 32 | "duration": duration, 33 | } 34 | 35 | 36 | if __name__ == '__main__': 37 | import uvicorn 38 | print('uuid:', uuid1()) 39 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.15_Extra_data_types/FastAPI_No.15_Extra_data_types_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from datetime import datetime, time, timedelta 3 | from uuid import UUID 4 | from uuid import uuid1 5 | from pydantic import BaseModel 6 | from fastapi import Body, FastAPI 7 | 8 | app = FastAPI() 9 | 10 | class Item(BaseModel): 11 | start_datetime: datetime 12 | end_datetime: datetime 13 | repeat_at: time 14 | process_after: timedelta 15 | start_process: str 16 | duration: str 17 | 18 | # 额外数据类型 19 | # https://fastapi.tiangolo.com/tutorial/extra-data-types/ 20 | @app.put("/items/{item_id}") 21 | async def read_items(item_id: UUID, item: Item): 22 | item.start_process = item.start_datetime + item.process_after 23 | item.duration = item.end_datetime - item.start_process 24 | return {"item_id": item_id, 'item':item } 25 | 26 | 27 | if __name__ == '__main__': 28 | import uvicorn 29 | print('uuid:', uuid1()) 30 | uvicorn.run(app, host="127.0.0.1", port=8000) 31 | 32 | -------------------------------------------------------------------------------- /FastAPI_No.16_Cookie_Parameters/FastAPI_No.16_Cookie_Parameters.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Cookie, FastAPI 3 | 4 | app = FastAPI() 5 | 6 | 7 | @app.get("/items/") 8 | async def read_items(*, ads_id: str = Cookie(None)): 9 | return {"ads_id": ads_id} 10 | 11 | 12 | if __name__ == '__main__': 13 | import uvicorn 14 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.17_Header_Parameters/FastAPI_No.17_Header_Parameters.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI, Header 3 | from typing import List 4 | app = FastAPI() 5 | 6 | 7 | @app.get("/items/") 8 | async def read_items(*, user_agent: str = Header(None), users_agent: str = Header(None)): 9 | return {"User-Agent": user_agent},{"AAAAA": user_agent},{'ABCD': users_agent} 10 | 11 | @app.get("/items2/") 12 | async def read_items2(x_token: List[str] = Header(None)): 13 | return {"X-Token values": x_token} 14 | 15 | 16 | if __name__ == '__main__': 17 | import uvicorn 18 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.18_Response_Model/FastAPI_No.18_Response_Model_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import List 3 | 4 | from fastapi import FastAPI 5 | from pydantic import BaseModel 6 | 7 | app = FastAPI() 8 | 9 | 10 | class Item(BaseModel): 11 | name: str 12 | description: str = None 13 | price: float 14 | tax: float = None 15 | tags: List[str] = [] 16 | 17 | 18 | @app.post("/items/", response_model =Item) 19 | async def create_item(item: Item): 20 | return item 21 | 22 | 23 | if __name__ == '__main__': 24 | import uvicorn 25 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.18_Response_Model/FastAPI_No.18_Response_Model_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from pydantic import BaseModel, EmailStr 4 | 5 | app = FastAPI() 6 | 7 | 8 | class UserIn(BaseModel): 9 | username: str 10 | password: str 11 | email: EmailStr 12 | full_name: str = None 13 | 14 | 15 | class UserOut(BaseModel): 16 | username: str 17 | email: EmailStr 18 | full_name: str = None 19 | 20 | 21 | @app.post("/user/", response_model=UserOut) 22 | async def create_user(*, user: UserIn): 23 | return user 24 | 25 | 26 | # pip install pydantic[email] 27 | if __name__ == '__main__': 28 | import uvicorn 29 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.18_Response_Model/FastAPI_No.18_Response_Model_3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import List 3 | 4 | from fastapi import FastAPI 5 | from pydantic import BaseModel 6 | 7 | app = FastAPI() 8 | 9 | 10 | class Item(BaseModel): 11 | name: str 12 | description: str = None 13 | price: float 14 | tax: float = 10.5 15 | tags: List[str] = [] 16 | 17 | 18 | items = { 19 | "foo": {"name": "Foo", "price": 50.2}, 20 | "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2}, 21 | "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.88, "tags": []}, 22 | } 23 | 24 | # response_model_exclude_unset=True 些默认值将不包括在响应中,仅包含实际设置的值。 25 | @app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True) 26 | async def read_item(item_id: str): 27 | return items[item_id] 28 | 29 | # response_model_exclude={"tax"} 是排除tax 30 | @app.get("/items/{item_id}/public", response_model=Item, response_model_exclude={"price"}) 31 | async def read_item_public_data(item_id: str): 32 | return items[item_id] 33 | 34 | 35 | if __name__ == '__main__': 36 | import uvicorn 37 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.18_Response_Model/FastAPI_No.18_Response_Model_4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from pydantic import BaseModel 4 | 5 | app = FastAPI() 6 | 7 | 8 | class Item(BaseModel): 9 | name: str 10 | description: str = None 11 | price: float 12 | tax: float = 10.5 13 | 14 | 15 | items = { 16 | "foo": {"name": "Foo", "price": 50.2}, 17 | "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2}, 18 | "baz": { 19 | "name": "Baz", 20 | "description": "There goes my baz", 21 | "price": 50.2, 22 | "tax": 10.5, 23 | }, 24 | } 25 | 26 | 27 | @app.get( 28 | "/items/{item_id}/name", 29 | response_model=Item, 30 | response_model_include=["name", "description", 'tax'], # 官方案例没有tax 31 | ) 32 | async def read_item_name(item_id: str): 33 | return items[item_id] 34 | 35 | 36 | @app.get("/items/{item_id}/public", response_model=Item, response_model_exclude=["tax"]) 37 | async def read_item_public_data(item_id: str): 38 | return items[item_id] 39 | 40 | 41 | 42 | if __name__ == '__main__': 43 | import uvicorn 44 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.18_Response_Model/注意可能需要安装这个.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.18_Response_Model/注意可能需要安装这个.png -------------------------------------------------------------------------------- /FastAPI_No.19_Extra_Model/FastAPI_No.19_Extra_Model_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from pydantic import BaseModel, EmailStr 4 | 5 | app = FastAPI() 6 | 7 | 8 | class UserIn(BaseModel): 9 | username: str 10 | password: str 11 | email: EmailStr 12 | full_name: str = None 13 | 14 | 15 | class UserOut(BaseModel): 16 | username: str 17 | email: EmailStr 18 | full_name: str = None 19 | 20 | 21 | class UserInDB(BaseModel): 22 | username: str 23 | hashed_password: str 24 | email: EmailStr 25 | full_name: str = None 26 | 27 | 28 | def fake_password_hasher(raw_password: str): 29 | return "supersecret" + raw_password 30 | 31 | 32 | def fake_save_user(user_in: UserIn): 33 | hashed_password = fake_password_hasher(user_in.password) 34 | user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password) 35 | print('user_in_db:', user_in_db) 36 | print("User saved! ..not really") 37 | return user_in_db 38 | 39 | 40 | @app.post("/user/", response_model=UserOut) 41 | async def create_user(*, user_in: UserIn): 42 | user_saved = fake_save_user(user_in) 43 | return user_saved 44 | 45 | 46 | if __name__ == '__main__': 47 | import uvicorn 48 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.19_Extra_Model/FastAPI_No.19_Extra_Model_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from pydantic import BaseModel, EmailStr 4 | 5 | app = FastAPI() 6 | 7 | 8 | class UserBase(BaseModel): 9 | username: str 10 | email: EmailStr 11 | full_name: str = None 12 | 13 | 14 | class UserIn(UserBase): 15 | password: str 16 | 17 | 18 | class UserOut(UserBase): 19 | pass 20 | 21 | 22 | class UserInDB(UserBase): 23 | hashed_password: str 24 | 25 | 26 | def fake_password_hasher(raw_password: str): 27 | return "supersecret" + raw_password 28 | 29 | 30 | def fake_save_user(user_in: UserIn): 31 | hashed_password = fake_password_hasher(user_in.password) 32 | user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password) 33 | print("User saved! ..not really") 34 | return user_in_db 35 | 36 | 37 | @app.post("/user/", response_model=UserOut) 38 | async def create_user(*, user_in: UserIn): 39 | user_saved = fake_save_user(user_in) 40 | return user_saved 41 | 42 | 43 | if __name__ == '__main__': 44 | import uvicorn 45 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.19_Extra_Model/FastAPI_No.19_Extra_Model_3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import Union 3 | 4 | from fastapi import FastAPI 5 | from pydantic import BaseModel 6 | 7 | app = FastAPI() 8 | 9 | 10 | class BaseItem(BaseModel): 11 | description: str 12 | type: str 13 | 14 | 15 | class CarItem(BaseItem): 16 | type = "car" 17 | 18 | 19 | class PlaneItem(BaseItem): 20 | type = "plane" 21 | size: int 22 | 23 | 24 | items = { 25 | "item1": {"description": "All my friends drive a low rider", "type": "car"}, 26 | "item2": { 27 | "description": "Music is my aeroplane, it's my aeroplane", 28 | "type": "plane", 29 | "size": 5, 30 | }, 31 | } 32 | 33 | 34 | @app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem]) 35 | async def read_item(item_id: str): 36 | return items[item_id] 37 | 38 | 39 | if __name__ == '__main__': 40 | import uvicorn 41 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.19_Extra_Model/FastAPI_No.19_Extra_Model_4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import List 3 | 4 | from fastapi import FastAPI 5 | from pydantic import BaseModel 6 | 7 | app = FastAPI() 8 | 9 | 10 | class Item(BaseModel): 11 | name: str 12 | description: str 13 | 14 | 15 | items = [ 16 | {"name": "Foo", "description": "There comes my hero"}, 17 | {"name": "Red", "description": "It's my aeroplane"}, 18 | ] 19 | 20 | 21 | @app.get("/items/", response_model=List[Item]) 22 | async def read_items(): 23 | return items 24 | 25 | 26 | if __name__ == '__main__': 27 | import uvicorn 28 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.19_Extra_Model/FastAPI_No.19_Extra_Model_5.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import Dict 3 | 4 | from fastapi import FastAPI 5 | 6 | app = FastAPI() 7 | 8 | 9 | @app.get("/keyword-weights/", response_model=Dict[str, float]) 10 | async def read_keyword_weights(): 11 | return {"foo": 2.3, "bar": 3.4} 12 | 13 | 14 | if __name__ == '__main__': 15 | import uvicorn 16 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.1_介绍/相关网址.txt: -------------------------------------------------------------------------------- 1 | 官方文档 2 | https://fastapi.tiangolo.com 3 | Github 4 | https://github.com/tiangolo/fastapi 5 | -------------------------------------------------------------------------------- /FastAPI_No.20.1_Handling_Errors/FastAPI_No.20.1_Handling_Errors_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI, HTTPException 3 | 4 | app = FastAPI() 5 | 6 | items = {"foo": "The Foo Wrestlers"} 7 | 8 | 9 | @app.get("/items/{item_id}") 10 | async def read_item(item_id: str): 11 | if item_id not in items: 12 | raise HTTPException(status_code=404, detail="Item not found") 13 | pass 14 | pass 15 | return {"item": items[item_id]} 16 | 17 | # 添加自定义标题 18 | @app.get("/items-header/{item_id}") 19 | async def read_item_header(item_id: str): 20 | if item_id not in items: 21 | raise HTTPException( 22 | status_code=404, 23 | detail="Item not found", 24 | headers={"X-Error": "There goes my error"}, 25 | # X-Error 自定义。例如,对于某些类型的安全性。OAuth 2.0和某些安全实用程序在内部需要/使用此功能。 26 | ) 27 | return {"item": items[item_id]} 28 | 29 | 30 | 31 | if __name__ == '__main__': 32 | import uvicorn 33 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.20.1_Handling_Errors/FastAPI_No.20.1_Handling_Errors_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | # from fastapi import FastAPI, Request 4 | # from fastapi.responses import JSONResponse 5 | from starlette.requests import Request 6 | from starlette.responses import JSONResponse 7 | 8 | # 安装自定义异常处理程序 9 | # 自定义异常UnicornException 10 | class UnicornException(Exception): # Exception 常规错误的基类 11 | def __init__(self, name: str): 12 | self.name = name 13 | 14 | app = FastAPI() 15 | 16 | @app.exception_handler(UnicornException) 17 | async def unicorn_exception_handler(request: Request, exc: UnicornException): 18 | return JSONResponse( 19 | status_code=404, # 418 I'm a teapot 20 | content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."}, 21 | ) 22 | 23 | 24 | @app.get("/unicorns/{name}") 25 | async def read_unicorn(name: str): 26 | if name == "yolo": 27 | raise UnicornException(name=name) 28 | return {"unicorn_name": name} 29 | 30 | 31 | if __name__ == '__main__': 32 | import uvicorn 33 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.20.1_Handling_Errors/FastAPI_No.20.1_Handling_Errors_3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI, HTTPException 3 | from fastapi.exceptions import RequestValidationError 4 | # from fastapi.responses import PlainTextResponse 5 | from starlette.responses import PlainTextResponse 6 | from starlette.exceptions import HTTPException as StarletteHTTPException 7 | 8 | app = FastAPI() 9 | 10 | # 覆盖默认的异常处理程序 11 | @app.exception_handler(StarletteHTTPException) # 重写HTTPException错误处理程序 12 | async def http_exception_handler(request, exc): 13 | return PlainTextResponse(str(exc.detail), status_code=exc.status_code) 14 | 15 | 16 | @app.exception_handler(RequestValidationError) # 导入超越请求验证异常 17 | async def validation_exception_handler(request, exc): 18 | return PlainTextResponse(str(exc), status_code=400) 19 | 20 | 21 | @app.get("/items/{item_id}") 22 | async def read_item(item_id: int): 23 | if item_id == 3: 24 | raise HTTPException(status_code=418, detail="Nope! I don't like 3.") # 418 I'm a teapot 25 | return {"item_id": item_id} 26 | 27 | 28 | if __name__ == '__main__': 29 | import uvicorn 30 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.20.1_Handling_Errors/FastAPI_No.20.1_Handling_Errors_4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | # from fastapi import FastAPI, Request, status 4 | from starlette.requests import Request 5 | from starlette import status 6 | from fastapi.encoders import jsonable_encoder 7 | from fastapi.exceptions import RequestValidationError 8 | # from fastapi.responses import JSONResponse 9 | from starlette.responses import JSONResponse 10 | from pydantic import BaseModel 11 | 12 | app = FastAPI() 13 | 14 | 15 | @app.exception_handler(RequestValidationError) # 请求验证错误 16 | async def validation_exception_handler(request: Request, exc: RequestValidationError): 17 | return JSONResponse( 18 | status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, 19 | content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}), 20 | ) 21 | 22 | 23 | class Item(BaseModel): 24 | title: str 25 | size: int 26 | 27 | 28 | @app.post("/items/") 29 | async def create_item(item: Item): 30 | return item 31 | 32 | 33 | if __name__ == '__main__': 34 | import uvicorn 35 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.20.1_Handling_Errors/FastAPI_No.20.1_Handling_Errors_5.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI, HTTPException 3 | from fastapi.exception_handlers import ( 4 | http_exception_handler, 5 | request_validation_exception_handler, 6 | ) 7 | from fastapi.exceptions import RequestValidationError 8 | from starlette.exceptions import HTTPException as StarletteHTTPException 9 | 10 | app = FastAPI() 11 | # FastAPI、starlette都有自己的HTTPException, 12 | # 区别是,FastAPI的HTTPException允许您添加要包含在响应头。OAuth 2.0和某些安全实用程序在内部需要/使用此功能。 13 | @app.exception_handler(StarletteHTTPException) 14 | async def custom_http_exception_handler(request, exc): 15 | print(f"OMG! An HTTP error!: {exc}") 16 | return await http_exception_handler(request, exc) # 重用Starlette的异常处理程序 17 | 18 | 19 | @app.exception_handler(RequestValidationError) 20 | async def validation_exception_handler(request, exc): 21 | print(f"OMG! The client sent invalid data!: {exc}") 22 | return await request_validation_exception_handler(request, exc) # 重用FastAPI的异常处理程序 23 | 24 | 25 | @app.get("/items/{item_id}") 26 | async def read_item(item_id: int): 27 | if item_id == 3: 28 | raise HTTPException(status_code=418, detail="Nope! I don't like 3.") # 418 I'm a teapot 29 | return {"item_id": item_id} 30 | 31 | 32 | if __name__ == '__main__': 33 | import uvicorn 34 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.20_Response_Status_Code/FastAPI_No.20_Response_Status.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from starlette import status 4 | 5 | app = FastAPI() 6 | 7 | 8 | @app.post("/items/", status_code=201) 9 | async def create_item(name: str): 10 | return {"name": name} 11 | 12 | @app.get("/items2/", status_code=201) 13 | async def create_item2(name: str): 14 | return {"name": name} 15 | 16 | @app.post("/items3/", status_code=status.HTTP_404_NOT_FOUND) 17 | async def create_item3(name: str): 18 | print('HTTP_404:', status.HTTP_404_NOT_FOUND) 19 | return {"name": name} 20 | 21 | @app.get("/i/", status_code=status.HTTP_404_NOT_FOUND) 22 | async def i(name: str): 23 | print('HTTP_404:', status.HTTP_404_NOT_FOUND) 24 | return {"name": name} 25 | 26 | 27 | if __name__ == '__main__': 28 | import uvicorn 29 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.21_Form_Data/FastAPI_No.21_Form_Data.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from starlette.requests import Request 3 | from fastapi import FastAPI, Form 4 | from starlette.templating import Jinja2Templates 5 | 6 | app = FastAPI() 7 | templates = Jinja2Templates(directory="templates") 8 | 9 | @app.post("/user/") 10 | async def users(username: str = Form(...), password: str = Form(...)): 11 | return {'username':username , 'password': password} 12 | 13 | 14 | @app.get("/") 15 | async def index(request: Request): 16 | return templates.TemplateResponse('post.html', {'request': request}) 17 | 18 | 19 | if __name__ == '__main__': 20 | import uvicorn 21 | uvicorn.run(app, host="127.0.0.1", port=8000) 22 | -------------------------------------------------------------------------------- /FastAPI_No.21_Form_Data/templates/post.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | 6 |
7 | 8 |
9 | 10 |
11 | 12 |

13 | 14 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /FastAPI_No.22_Request_Files/FastAPI_No.22_Request_Files.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from starlette.requests import Request 3 | from fastapi import FastAPI, File, UploadFile 4 | from starlette.templating import Jinja2Templates 5 | 6 | app = FastAPI() 7 | templates = Jinja2Templates(directory="templates") 8 | 9 | 10 | @app.post("/create_file/") 11 | async def create_file(file:bytes = File(...), fileb: UploadFile = File(...)): 12 | return {"file_size" : len(file), 13 | "fileb_content_type" : fileb.content_type} 14 | 15 | 16 | @app.get("/") 17 | async def main(request: Request): 18 | return templates.TemplateResponse('post.html', {'request': request}) 19 | 20 | 21 | if __name__ == '__main__': 22 | import uvicorn 23 | uvicorn.run(app, host="127.0.0.1", port=8000) 24 | -------------------------------------------------------------------------------- /FastAPI_No.22_Request_Files/templates/post.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 |

6 | 7 |
8 | 9 | -------------------------------------------------------------------------------- /FastAPI_No.23_Request_Forms_and_Files/FastAPI_No.23_Request_Forms_and_Files.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import List 3 | from starlette.requests import Request 4 | from fastapi import FastAPI, Form, File, UploadFile 5 | from starlette.templating import Jinja2Templates 6 | 7 | app = FastAPI() 8 | templates = Jinja2Templates(directory="templates") 9 | 10 | 11 | @app.post("/create_file/") 12 | async def create_file(file: bytes = File(...), 13 | fileb: UploadFile = File(...), 14 | notes: str = Form(...)): 15 | return {"file_size" : len(file), 16 | "notes" : notes, 17 | "fileb_content_type" : fileb.content_type} 18 | 19 | 20 | @app.get("/") 21 | async def main(request: Request): 22 | return templates.TemplateResponse('post.html', {'request': request}) 23 | 24 | 25 | if __name__ == '__main__': 26 | import uvicorn 27 | uvicorn.run(app, host="127.0.0.1", port=8000) 28 | -------------------------------------------------------------------------------- /FastAPI_No.23_Request_Forms_and_Files/templates/post.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

5 |

6 |

7 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /FastAPI_No.24_JSON_Compatible_Encoder/FastAPI_No.24_JSON_Compatible_Encoder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from datetime import datetime 3 | 4 | from fastapi import FastAPI 5 | from fastapi.encoders import jsonable_encoder 6 | from pydantic import BaseModel 7 | 8 | fake_db = {} 9 | 10 | 11 | class Item(BaseModel): 12 | title: str 13 | timestamp: datetime 14 | description: str = None 15 | 16 | 17 | app = FastAPI() 18 | 19 | 20 | @app.put("/items/{id}") 21 | def update_item(id: str, item: Item): 22 | json_compatible_item_data = jsonable_encoder(item) 23 | # jsonable_encoder实际上由FastAPI在内部用于转换数据。但这在许多其他情况下很有用。 24 | fake_db[id] = json_compatible_item_data 25 | print(json_compatible_item_data) 26 | print(type(json_compatible_item_data)) 27 | print(fake_db) 28 | print(type(fake_db)) 29 | # return fake_db 30 | 31 | 32 | if __name__ == '__main__': 33 | import uvicorn 34 | uvicorn.run(app, host="127.0.0.1", port=8000) 35 | -------------------------------------------------------------------------------- /FastAPI_No.25_Body_updates/FastAPI_No.25_Body_updates_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import List 3 | 4 | from fastapi import FastAPI 5 | from fastapi.encoders import jsonable_encoder 6 | from pydantic import BaseModel 7 | 8 | app = FastAPI() 9 | 10 | 11 | class Item(BaseModel): 12 | name: str = None 13 | description: str = None 14 | price: float = None 15 | tax: float = 10.5 16 | tags: List[str] = [] 17 | 18 | 19 | items = { 20 | "foo": {"name": "Foo", "price": 50.2}, 21 | "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2}, 22 | "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []}, 23 | } 24 | 25 | 26 | @app.get("/items/{item_id}", response_model=Item) 27 | async def read_item(item_id: str): 28 | return items[item_id] 29 | 30 | 31 | @app.put("/items/{item_id}", response_model=Item) 32 | async def update_item(item_id: str, item: Item): 33 | update_item_encoded = jsonable_encoder(item) 34 | items[item_id] = update_item_encoded 35 | print(items) 36 | return update_item_encoded 37 | 38 | 39 | if __name__ == '__main__': 40 | import uvicorn 41 | uvicorn.run(app, host="127.0.0.1", port=8000) 42 | -------------------------------------------------------------------------------- /FastAPI_No.25_Body_updates/FastAPI_No.25_Body_updates_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import List 3 | 4 | from fastapi import FastAPI 5 | from fastapi.encoders import jsonable_encoder 6 | from pydantic import BaseModel 7 | 8 | app = FastAPI() 9 | 10 | 11 | class Item(BaseModel): 12 | name: str = None 13 | description: str = None 14 | price: float = None 15 | tax: float = 10.5 16 | tags: List[str] = [] 17 | 18 | 19 | items = { 20 | "foo": {"name": "Foo", "price": 50.2}, 21 | "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2}, 22 | "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []}, 23 | } 24 | 25 | 26 | @app.get("/items/{item_id}", response_model=Item) 27 | async def read_item(item_id: str): 28 | return items[item_id] 29 | 30 | 31 | @app.patch("/items/{item_id}", response_model=Item) 32 | async def update_item(item_id: str, item: Item): 33 | stored_item_data = items[item_id] # 存储项目数据 34 | stored_item_model = Item(**stored_item_data) # 存储项目模型 35 | update_data = item.dict(exclude_unset=True) 36 | print('update_data', update_data)################# 37 | updated_item = stored_item_model.copy(update=update_data) 38 | # print('update_item', update_item) 39 | print('updated_item', jsonable_encoder(updated_item))################# 40 | items[item_id] = jsonable_encoder(updated_item) 41 | print('items[item_id]', items[item_id])########### 42 | return updated_item 43 | 44 | 45 | if __name__ == '__main__': 46 | import uvicorn 47 | uvicorn.run(app, host="127.0.0.1", port=8000) 48 | -------------------------------------------------------------------------------- /FastAPI_No.26_Dependencies/FastAPI_No.26_Dependencies_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Depends, FastAPI 3 | import time 4 | 5 | app = FastAPI() 6 | #简单介绍 7 | 8 | async def common_parameters(q: str = None, skip: int = 0, limit: int = 100): 9 | limit += 66 10 | return {"q": q, "skip": skip, "limit": limit} 11 | 12 | 13 | @app.get("/items/") 14 | async def read_items(commons: dict = Depends(common_parameters)): 15 | # 什么可以作为一个依赖?要‘可调用的’比如说类、函数、包等 16 | commons['skip'] += 10 17 | return commons 18 | 19 | 20 | @app.get("/users/") 21 | async def read_users(commons: dict = Depends(common_parameters)): 22 | return commons 23 | 24 | 25 | if __name__ == '__main__': 26 | import uvicorn 27 | uvicorn.run(app, host="127.0.0.1", port=8000) 28 | 29 | -------------------------------------------------------------------------------- /FastAPI_No.26_Dependencies/FastAPI_No.26_Dependencies_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Depends, FastAPI 3 | 4 | app = FastAPI() 5 | # 类作为依赖项 6 | 7 | fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] 8 | 9 | 10 | # async def common_parameters(q: str = None, skip: int = 0, limit: int = 100): 11 | # return {"q": q, "skip": skip, "limit": limit} 12 | 13 | # common = CommonQueryParams(),可调用,所以可以做为‘依赖’,FastAPI就会分析定义了参数 14 | class CommonQueryParams: 15 | def __init__(self, q: str = None, skip: int = 0, limit: int = 100): 16 | # __init__用于创建类实例的方法,且这些参数是FastAPI将用来“解决”依赖关系的参数 17 | self.q = q 18 | self.skip = skip 19 | self.limit = limit 20 | 21 | 22 | @app.get("/items/") 23 | async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)): # 声明依赖项。FastAPI来了解依赖项的内容 24 | # CommonQueryParams FastAPI没有任何特殊含义。不会将其用于数据转换,验证等 25 | # async def read_items(commons=Depends(CommonQueryParams)): √√√√√ 26 | # async def read_items(commons: CommonQueryParams = Depends()): √√√√√ 在相关性是明确的类的情况下 27 | response = {} 28 | if commons.q: 29 | response.update({"q": commons.q}) 30 | # items = fake_items_db[commons.skip: commons.skip + commons.limit] 31 | items = fake_items_db[commons.skip : commons.skip + commons.limit] 32 | response.update({"items": items}) 33 | return response 34 | 35 | 36 | if __name__ == '__main__': 37 | import uvicorn 38 | uvicorn.run(app, host="127.0.0.1", port=8000) 39 | 40 | 41 | -------------------------------------------------------------------------------- /FastAPI_No.26_Dependencies/FastAPI_No.26_Dependencies_3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Cookie, Depends, FastAPI 3 | 4 | app = FastAPI() 5 | 6 | 7 | def query_extractor(q: str = None): 8 | return q 9 | 10 | 11 | def query_or_cookie_extractor( 12 | q: str = Depends(query_extractor), last_query: str = Cookie(None) 13 | ): 14 | if not q: 15 | return last_query 16 | return q 17 | 18 | 19 | @app.get("/items/") 20 | async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)): 21 | return {"q_or_cookie": query_or_default} 22 | 23 | 24 | if __name__ == '__main__': 25 | import uvicorn 26 | uvicorn.run(app, host="127.0.0.1", port=8000) 27 | 28 | 29 | # 多次使用相同的依赖项 -------------------------------------------------------------------------------- /FastAPI_No.26_Dependencies/FastAPI_No.26_Dependencies_4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Depends, FastAPI, Header, HTTPException 3 | 4 | app = FastAPI() 5 | 6 | 7 | async def verify_token(x_token: str = Header(...)): 8 | if x_token != "fake-super-secret-token": 9 | raise HTTPException(status_code=400, detail="X-Token header invalid") 10 | 11 | 12 | async def verify_key(x_key: str = Header(...)): 13 | if x_key != "fake-super-secret-key": 14 | raise HTTPException(status_code=400, detail="X-Key header invalid") 15 | return x_key 16 | 17 | 18 | @app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)]) 19 | async def read_items(): 20 | return [{"item": "Foo"}, {"item": "Bar"}] 21 | 22 | 23 | if __name__ == '__main__': 24 | import uvicorn 25 | uvicorn.run(app, host="127.0.0.1", port=8000) 26 | 27 | -------------------------------------------------------------------------------- /FastAPI_No.27_Security/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.27_Security/1.jpg -------------------------------------------------------------------------------- /FastAPI_No.27_Security/FastAPI_No.27_Security_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import Optional 3 | 4 | from fastapi import Depends, FastAPI 5 | from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm 6 | from pydantic import BaseModel 7 | 8 | app = FastAPI() 9 | 10 | oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token") 11 | # 声明该URL是客户端应用于获取令牌的URL。该信息在OpenAPI中使用,然后在交互式API文档系统中使用。 12 | # 该oauth2_scheme变量的一个实例OAuth2PasswordBearer,但它也是一个“通知”。 13 | # oauth2_scheme是令牌对象,token: str = Depends(oauth2_scheme)后就是之前加密的令牌 14 | 15 | @app.get("/items/") 16 | async def read_items(token: str = Depends(oauth2_scheme)): 17 | return {"token": token} 18 | # 尚未验证令牌的有效性 19 | 20 | 21 | if __name__ == '__main__': 22 | import uvicorn 23 | uvicorn.run(app, host="127.0.0.1", port=8000) 24 | 25 | -------------------------------------------------------------------------------- /FastAPI_No.27_Security/FastAPI_No.27_Security_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import Optional 3 | 4 | from fastapi import Depends, FastAPI, Header 5 | from fastapi.security import OAuth2PasswordBearer 6 | from pydantic import BaseModel 7 | 8 | app = FastAPI() 9 | # oauth2_scheme是令牌对象,token: str = Depends(oauth2_scheme)后就是之前加密的令牌 10 | oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token") 11 | 12 | class User(BaseModel): 13 | username: str 14 | email: Optional[str] = None 15 | full_name: Optional[str] = None 16 | disabled: Optional[bool] = None 17 | 18 | 19 | def fake_decode_token(token): 20 | return User( 21 | username=token + "fakedecoded", email="john@example.com", full_name="John Doe" 22 | ) 23 | 24 | 25 | async def get_current_user(token: str = Depends(oauth2_scheme)): 26 | print('token', token) 27 | print('token type', type(token)) 28 | user = fake_decode_token(token) 29 | return user 30 | 31 | 32 | @app.get("/users/me")# Authorization: Bearer joxxxxxxx 33 | async def read_users_me(current_user: User = Depends(get_current_user)): # Authorization: str = Header(...), 34 | return current_user 35 | 36 | # 在同一文件中混合了安全性,数据模型,功能,路径操作。 37 | if __name__ == '__main__': 38 | import uvicorn 39 | uvicorn.run(app, host="127.0.0.1", port=8000) 40 | 41 | 42 | -------------------------------------------------------------------------------- /FastAPI_No.27_Security/FastAPI_No.27_Security_3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import Depends, FastAPI, HTTPException # , status 3 | from starlette import status 4 | from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm 5 | from pydantic import BaseModel 6 | 7 | # 用户数据(模拟) 8 | fake_users_db = { 9 | "johndoe": { 10 | "username": "johndoe", 11 | "full_name": "John Doe", 12 | "email": "johndoe@example.com", 13 | "hashed_password": "fakehashedsecret", 14 | "disabled": False, 15 | }, 16 | "alice": { 17 | "username": "alice", 18 | "full_name": "Alice Wonderson", 19 | "email": "alice@example.com", 20 | "hashed_password": "fakehashedsecret2", 21 | "disabled": True, # 关闭此用户 22 | }, 23 | } 24 | 25 | app = FastAPI() 26 | 27 | # 哈希密码(模拟) 28 | def fake_hash_password(password: str): 29 | return "fakehashed" + password 30 | # oauth2_scheme是令牌对象,token: str = Depends(oauth2_scheme)后就是之前加密的令牌 31 | oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token") # Bearer 持票人(承载、数据载体) 32 | 33 | # 用户信息模型 34 | class User(BaseModel): 35 | username: str 36 | email: str = None 37 | full_name: str = None 38 | disabled: bool = None 39 | # 用户输入模型 40 | class UserInDB(User): 41 | hashed_password: str #哈希密码 42 | username: str # 此行多余,为了vscode不报错而已。 43 | # 获取用户 44 | def get_user(db, username: str): 45 | if username in db: 46 | user_dict = db[username] 47 | return UserInDB(**user_dict) 48 | 49 | # 解码令牌(模拟) 50 | def fake_decode_token(token): 51 | # This doesn't provide any security at all 52 | # Check the next version 53 | user = get_user(fake_users_db, token) 54 | return user 55 | 56 | # 获取当前用户 57 | # 如果用户不存在或处于非活动状态,则这两个依赖项都将仅返回HTTP错误。 58 | async def get_current_user(token: str = Depends(oauth2_scheme)): 59 | print('oauth2_scheme', oauth2_scheme) 60 | print('token', token) 61 | user = fake_decode_token(token) 62 | if not user: 63 | raise HTTPException( 64 | status_code=status.HTTP_401_UNAUTHORIZED, 65 | detail="Invalid authentication credentials", # 无效的身份验证凭据 66 | headers={"WWW-Authenticate": "Bearer"}, 67 | ) 68 | return user 69 | 70 | # 获取当前活跃用户,get(read_users_me)专属 71 | async def get_current_active_user(current_user: User = Depends(get_current_user)): 72 | if current_user.disabled: 73 | raise HTTPException(status_code=400, detail="Inactive user") 74 | return current_user 75 | 76 | 77 | @app.post("/token") # name = johndoe,alice password = secret,secret2 78 | async def login(form_data: OAuth2PasswordRequestForm = Depends()): 79 | # 使用username来自表单字段的从(假)数据库获取用户数据。 80 | user_dict = fake_users_db.get(form_data.username) 81 | if not user_dict: 82 | raise HTTPException(status_code=400, detail="Incorrect username or password") 83 | # 先将这些数据放到Pydantic UserInDB模型中 84 | user = UserInDB(**user_dict) 85 | hashed_password = fake_hash_password(form_data.password) 86 | if not hashed_password == user.hashed_password: 87 | raise HTTPException(status_code=400, detail="Incorrect username or password") 88 | # 如果正确返回 89 | return {"access_token": user.username, "token_type": "bearer"} 90 | 91 | 92 | @app.get("/users/me") 93 | async def read_users_me(current_user: User = Depends(get_current_active_user)): 94 | return current_user 95 | 96 | 97 | if __name__ == '__main__': 98 | import uvicorn 99 | uvicorn.run(app, host="127.0.0.1", port=8000) 100 | 101 | -------------------------------------------------------------------------------- /FastAPI_No.27_Security/FastAPI_No.27_Security_4.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from datetime import datetime, timedelta 3 | import jwt 4 | from fastapi import Depends, FastAPI, HTTPException # , status 5 | from starlette import status 6 | from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm 7 | from jwt import PyJWTError 8 | from passlib.context import CryptContext # passlib 处理哈希加密的包 9 | from pydantic import BaseModel 10 | 11 | # to get a string like this run: openssl rand -hex 32 12 | SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"# 密钥 13 | ALGORITHM = "HS256" # 算法 14 | ACCESS_TOKEN_EXPIRE_MINUTES = 30 # 访问令牌过期分钟 15 | 16 | # 用户数据(模拟) 17 | fake_users_db = { 18 | "johndoe": { 19 | "username": "johndoe", 20 | "full_name": "John Doe", 21 | "email": "johndoe@example.com", 22 | "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW", 23 | "disabled": False, 24 | } 25 | } 26 | 27 | 28 | 29 | class Token(BaseModel): # 令牌空壳 30 | access_token: str 31 | token_type: str 32 | class TokenData(BaseModel): # 令牌数据 33 | username: str = None 34 | class User(BaseModel): # 用户基础模型 35 | username: str 36 | email: str = None 37 | full_name: str = None 38 | disabled: bool = None 39 | class UserInDB(User): # 用户输入数据模型 40 | hashed_password: str 41 | username: str # 此行多余,为了vscode不报错而已。 42 | # Context是上下文 CryptContext是密码上下文 schemes是计划 deprecated是不赞成(强烈反对) 43 | # bcrypt是加密算法 44 | pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") 45 | # oauth2_scheme是令牌对象,token: str = Depends(oauth2_scheme)后就是之前加密的令牌 46 | oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/token") 47 | app = FastAPI() 48 | 49 | 50 | 51 | # verify_password验证密码 plain_password普通密码 hashed_password哈希密码 52 | def verify_password(plain_password, hashed_password): 53 | return pwd_context.verify(plain_password, hashed_password) 54 | # 获取密码哈希 55 | def get_password_hash(password): 56 | return pwd_context.hash(password) 57 | # 获取用户 58 | def get_user(db, username: str): 59 | if username in db: 60 | user_dict = db[username] 61 | return UserInDB(**user_dict) 62 | # 验证用户 63 | def authenticate_user(fake_db, username: str, password: str): 64 | user = get_user(fake_db, username) 65 | if not user or not verify_password(password, user.hashed_password): 66 | raise HTTPException( 67 | status_code=status.HTTP_401_UNAUTHORIZED, 68 | detail="Incorrect username or password", 69 | headers={"WWW-Authenticate": "Bearer"}, 70 | ) 71 | print('验证用户user :', user) 72 | print('验证用户type :', type(user)) 73 | return user # 74 | 75 | 76 | 77 | 78 | # 创建访问令牌 79 | def create_access_token(*, data: dict, expires_delta: timedelta = None): 80 | to_encode = data.copy() 81 | expire = datetime.utcnow() + expires_delta # expire 令牌到期时间 82 | to_encode.update({"exp": expire}) 83 | encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) 84 | return encoded_jwt 85 | 86 | 87 | 88 | # 获取当前用户 89 | async def get_current_user(token: str = Depends(oauth2_scheme)): 90 | credentials_exception = HTTPException( 91 | status_code=status.HTTP_401_UNAUTHORIZED, 92 | detail="Could not validate credentials", 93 | headers={"WWW-Authenticate": "Bearer"}, 94 | ) 95 | try: 96 | payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) 97 | username: str = payload.get("sub") 98 | if username is None: 99 | raise credentials_exception 100 | token_data = TokenData(username=username) 101 | except PyJWTError: 102 | raise credentials_exception 103 | user = get_user(fake_users_db, username=token_data.username) 104 | if user is None: 105 | raise credentials_exception 106 | print('获取当前用户user :', user) 107 | print('获取当前用户type :', type(user)) 108 | return user 109 | # 获取当前激活用户 110 | async def get_current_active_user(current_user: User = Depends(get_current_user)): 111 | if current_user.disabled: 112 | raise HTTPException(status_code=400, detail="Inactive user") 113 | return current_user 114 | 115 | 116 | 117 | 118 | # name = johndoe password = secret 119 | @app.post("/token", response_model=Token) 120 | async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()): 121 | # 1、验证用户 122 | user = authenticate_user(fake_users_db, form_data.username, form_data.password) # 验证用户 123 | # 2、access_token_expires访问令牌过期 124 | access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) # timedelta表示两个datetime对象之间的差异。(来自datetime包) 125 | # 3、create_access_token创建访问令牌 126 | access_token = create_access_token(data={"sub": user.username}, 127 | expires_delta=access_token_expires) 128 | # 返回 129 | return {"access_token": access_token, "token_type": "bearer"} 130 | 131 | @app.get("/users/me/", response_model=User) 132 | async def read_users_me(current_user: User = Depends(get_current_active_user)): 133 | return current_user 134 | 135 | @app.get("/users/me/items/") 136 | async def read_own_items(current_user: User = Depends(get_current_active_user)): 137 | return [{"item_id": "Foo", "owner": current_user.username}] 138 | 139 | 140 | 141 | 142 | 143 | 144 | if __name__ == '__main__': 145 | import uvicorn 146 | uvicorn.run(app, host="127.0.0.1", port=8000) 147 | 148 | -------------------------------------------------------------------------------- /FastAPI_No.27_Security/test_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from datetime import datetime, timedelta 3 | 4 | import jwt 5 | from fastapi import Depends, FastAPI, HTTPException # , status 6 | from starlette import status 7 | from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm 8 | from jwt import PyJWTError 9 | from passlib.context import CryptContext # passlib 处理哈希加密的包 10 | from pydantic import BaseModel 11 | 12 | 13 | 14 | pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") 15 | 16 | # verify_password验证密码 plain_password普通密码 hashed_password哈希密码 17 | def verify_password(plain_password, hashed_password): 18 | return pwd_context.verify(plain_password, hashed_password) 19 | # 获取密码哈希 20 | def get_password_hash(password): 21 | return pwd_context.hash(password) 22 | 23 | 24 | if __name__ == "__main__": 25 | ############################本章节哈希验证用法############################ 26 | xxx = get_password_hash('cccccc') 27 | yyy = get_password_hash('cccccc') 28 | print(xxx) 29 | print(yyy) 30 | print('verify_password',verify_password('cccccc',xxx)) 31 | print('verify_password',verify_password('cccccc',yyy)) 32 | print('verify_password',verify_password('secret','$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW')) 33 | 34 | 35 | 36 | ############################本章节时间差(timedelta)用法########################### 37 | from datetime import datetime 38 | from datetime import timedelta 39 | aDay = timedelta(minutes=30) # timedelta表示两个datetime对象之间的差异。(来自datetime包) 40 | now = datetime.now() + aDay 41 | print(aDay) 42 | print(datetime.now()) 43 | print(now ,type(now)) 44 | 45 | -------------------------------------------------------------------------------- /FastAPI_No.28_Middleware+CORS/CORS.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.28_Middleware+CORS/CORS.jpg -------------------------------------------------------------------------------- /FastAPI_No.28_Middleware+CORS/FastAPI_No.28_CORS.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from starlette.requests import Request 4 | # from fastapi.middleware.cors import CORSMiddleware 5 | from starlette.middleware.cors import CORSMiddleware 6 | from starlette.staticfiles import StaticFiles 7 | from starlette.templating import Jinja2Templates 8 | 9 | app = FastAPI() 10 | templates = Jinja2Templates(directory="templates") 11 | app.mount('/static', StaticFiles(directory='static'), name='static') 12 | 13 | 14 | # origins = [ 15 | # "http://localhost.tiangolo.com", 16 | # "https://localhost.tiangolo.com", 17 | # "http://localhost", 18 | # "http://localhost:8080", 19 | # "http://127.0.0.1:8888" 20 | 21 | # ] 22 | 23 | # app.add_middleware( # 添加中间件 24 | # CORSMiddleware, # CORS中间件类 25 | # allow_origins=origins, # allow_origins=['*'], # 允许起源所有 26 | # allow_credentials=True, # 允许凭据 27 | # allow_methods=["*"], # 允许方法 28 | # allow_headers=["*"], # 允许头部 29 | # ) 30 | 31 | @app.get("/") 32 | async def main(request: Request): 33 | return templates.TemplateResponse('index.html', {'request': request}) 34 | 35 | 36 | if __name__ == '__main__': 37 | import uvicorn 38 | uvicorn.run(app, host="127.0.0.1", port=8000) 39 | 40 | -------------------------------------------------------------------------------- /FastAPI_No.28_Middleware+CORS/FastAPI_No.28_Middleware.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import time 3 | 4 | from fastapi import FastAPI #, Request 5 | from starlette.requests import Request 6 | 7 | app = FastAPI() 8 | 9 | 10 | @app.middleware("http") 11 | async def add_process_time_header(request: Request, call_next): 12 | start_time = time.time() 13 | response = await call_next(request) 14 | process_time = time.time() - start_time 15 | response.headers["X-Process-Time"] = str(process_time) 16 | print(response.headers) 17 | return response 18 | 19 | 20 | @app.get("/") 21 | async def main(): 22 | return {"message": "Hello World"} 23 | 24 | 25 | 26 | 27 | if __name__ == '__main__': 28 | import uvicorn 29 | uvicorn.run(app, host="127.0.0.1", port=8000) 30 | 31 | -------------------------------------------------------------------------------- /FastAPI_No.28_Middleware+CORS/FastAPI_No.2_helloworld.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from starlette.middleware.cors import CORSMiddleware 4 | 5 | app = FastAPI() 6 | 7 | origins = [ 8 | "http://localhost.tiangolo.com", 9 | "https://localhost.tiangolo.com", 10 | "http://localhost", 11 | "http://localhost:8080", 12 | "http://127.0.0.1:8000" 13 | 14 | ] 15 | 16 | app.add_middleware( # 添加中间件 17 | CORSMiddleware, # CORS中间件类 18 | allow_origins=origins, # 允许起源 19 | allow_credentials=True, # 允许凭据 20 | allow_methods=["*"], # 允许方法 21 | allow_headers=["*"], # 允许头部 22 | ) 23 | 24 | @app.get("/") 25 | async def main(): 26 | return {"message": "Hello FastAPI, from get..."} 27 | 28 | @app.post("/") 29 | async def main1(q: str = None): 30 | return {"message": "Hello FastAPI, from post..."} 31 | 32 | 33 | if __name__ == '__main__': 34 | import uvicorn 35 | uvicorn.run(app, host="127.0.0.1", port=8888) 36 | 37 | -------------------------------------------------------------------------------- /FastAPI_No.28_Middleware+CORS/Middleware.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.28_Middleware+CORS/Middleware.jpg -------------------------------------------------------------------------------- /FastAPI_No.28_Middleware+CORS/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | index 8 | 9 | 10 | 11 | 12 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/1_ORM.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.29_SQLDatabases/1_ORM.jpg -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/2_Sqlalchemy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.29_SQLDatabases/2_Sqlalchemy.jpg -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/3_yield.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.29_SQLDatabases/3_yield.jpg -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/sql_app/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/sql_app/alt_main.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from fastapi import Depends, FastAPI, HTTPException 4 | from sqlalchemy.orm import Session 5 | from starlette.requests import Request 6 | from starlette.responses import Response 7 | 8 | import crud, models, schemas 9 | from database import SessionLocal, engine 10 | 11 | models.Base.metadata.create_all(bind=engine) 12 | 13 | app = FastAPI() 14 | 15 | # 中间件 16 | @app.middleware("http") 17 | async def db_session_middleware(request: Request, call_next): # 数据库会话中间件 18 | response = Response("Internal server error", status_code=500) 19 | try: 20 | request.state.db = SessionLocal() # 本地会话 21 | response = await call_next(request) 22 | finally: 23 | request.state.db.close() 24 | return response 25 | 26 | 27 | # Dependency 28 | def get_db(request: Request): 29 | return request.state.db 30 | 31 | 32 | @app.post("/users/", response_model=schemas.User) 33 | def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)): 34 | db_user = crud.get_user_by_email(db, email=user.email) 35 | if db_user: 36 | raise HTTPException(status_code=400, detail="Email already registered") 37 | return crud.create_user(db=db, user=user) 38 | 39 | 40 | @app.get("/users/", response_model=List[schemas.User]) 41 | def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): 42 | users = crud.get_users(db, skip=skip, limit=limit) 43 | return users 44 | 45 | 46 | @app.get("/users/{user_id}", response_model=schemas.User) 47 | def read_user(user_id: int, db: Session = Depends(get_db)): 48 | db_user = crud.get_user(db, user_id=user_id) 49 | if db_user is None: 50 | raise HTTPException(status_code=404, detail="User not found") 51 | return db_user 52 | 53 | 54 | @app.post("/users/{user_id}/items/", response_model=schemas.Item) 55 | def create_item_for_user( 56 | user_id: int, item: schemas.ItemCreate, db: Session = Depends(get_db) 57 | ): 58 | return crud.create_user_item(db=db, item=item, user_id=user_id) 59 | 60 | 61 | @app.get("/items/", response_model=List[schemas.Item]) 62 | def read_items(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): 63 | items = crud.get_items(db, skip=skip, limit=limit) 64 | return items 65 | 66 | 67 | if __name__ == '__main__': 68 | import uvicorn 69 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/sql_app/crud.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.orm import Session # 会话 2 | 3 | import models, schemas # 模式 4 | 5 | # 通过id查询用户信息 6 | def get_user(db: Session, user_id: int): 7 | return db.query(models.User).filter(models.User.id == user_id).first() 8 | # 过滤器 9 | # 通过email查询用户信息 10 | def get_user_by_email(db: Session, email: str): 11 | return db.query(models.User).filter(models.User.email == email).first() 12 | 13 | # 通过id范围查询用户信息 14 | def get_users(db: Session, skip: int = 0, limit: int = 100): 15 | # 初值 末值 16 | return db.query(models.User).offset(skip).limit(limit).all() 17 | 18 | # 新建用户 19 | def create_user(db: Session, user: schemas.UserCreate): 20 | fake_hashed_password = user.password + "notreallyhashed" 21 | db_user = models.User(email=user.email, hashed_password=fake_hashed_password) 22 | db.add(db_user) 23 | db.commit() 24 | db.refresh(db_user) 25 | return db_user 26 | 27 | # 获取用户拥有的项目 28 | def get_items(db: Session, skip: int = 0, limit: int = 100): 29 | return db.query(models.Item).offset(skip).limit(limit).all() 30 | 31 | # 新建用户拥有的项目 32 | def create_user_item(db: Session, item: schemas.ItemCreate, user_id: int): 33 | db_item = models.Item(**item.dict(), owner_id=user_id) 34 | db.add(db_item) 35 | db.commit() 36 | db.refresh(db_item) 37 | return db_item 38 | -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/sql_app/database.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db" 6 | # SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db" 7 | 8 | engine = create_engine( 9 | SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} 10 | ) 11 | SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) # sessionmaker 会话生成器 12 | 13 | Base = declarative_base() 14 | -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/sql_app/main.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from fastapi import Depends, FastAPI, HTTPException 4 | from sqlalchemy.orm import Session 5 | 6 | import crud, models, schemas 7 | from database import SessionLocal, engine 8 | 9 | models.Base.metadata.create_all(bind=engine) 10 | 11 | app = FastAPI() 12 | 13 | 14 | # Dependency 依赖项 15 | def get_db(): 16 | try: 17 | db = SessionLocal() # 本地会话 18 | yield db 19 | finally: 20 | db.close() 21 | print('数据库已关闭') 22 | 23 | 24 | 25 | # 新建用户 26 | @app.post("/users/", response_model=schemas.User) 27 | def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)): 28 | db_user = crud.get_user_by_email(db, email=user.email) 29 | if db_user: 30 | raise HTTPException(status_code=400, detail="Email already registered") 31 | # 电子邮件已注册 32 | return crud.create_user(db=db, user=user) 33 | 34 | # 读取用户(用户ID范围) 35 | @app.get("/users/", response_model=List[schemas.User]) 36 | def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): 37 | users = crud.get_users(db, skip=skip, limit=limit) 38 | return users 39 | 40 | # 用ID的方式读取用户 41 | @app.get("/users/{user_id}", response_model=schemas.User) 42 | def read_user(user_id: int, db: Session = Depends(get_db)): 43 | db_user = crud.get_user(db, user_id=user_id) 44 | if db_user is None: 45 | raise HTTPException(status_code=404, detail="User not found") 46 | return db_user 47 | 48 | # 设置用户拥有的项目(权限或作用域) 49 | @app.post("/users/{user_id}/items/", response_model=schemas.Item) 50 | def create_item_for_user( 51 | user_id: int, item: schemas.ItemCreate, db: Session = Depends(get_db) 52 | ): 53 | return crud.create_user_item(db=db, item=item, user_id=user_id) 54 | 55 | # 读取用户项目(权限或作用域) 56 | @app.get("/items/", response_model=List[schemas.Item]) 57 | def read_items(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): 58 | items = crud.get_items(db, skip=skip, limit=limit) 59 | return items 60 | 61 | 62 | if __name__ == '__main__': 63 | import uvicorn 64 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/sql_app/models.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import Boolean, Column, ForeignKey, Integer, String 2 | from sqlalchemy.orm import relationship 3 | 4 | from database import Base # 已声明的数据库 5 | """row:行 column:列""" 6 | 7 | class User(Base): 8 | __tablename__ = "users" 9 | 10 | id = Column(Integer, primary_key=True, index=True) 11 | email = Column(String, unique=True, index=True) 12 | hashed_password = Column(String) 13 | is_active = Column(Boolean, default=True) 14 | 15 | items = relationship("Item", back_populates="owner") 16 | # 关系 17 | 18 | 19 | class Item(Base): 20 | __tablename__ = "items" 21 | 22 | id = Column(Integer, primary_key=True, index=True) 23 | title = Column(String, index=True) 24 | description = Column(String, index=True) 25 | owner_id = Column(Integer, ForeignKey("users.id")) 26 | 27 | owner = relationship("User", back_populates="items") 28 | -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/sql_app/schemas.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class ItemBase(BaseModel): 7 | title: str 8 | description: str = None 9 | 10 | 11 | class ItemCreate(ItemBase): 12 | pass 13 | 14 | 15 | class Item(ItemBase): 16 | id: int 17 | owner_id: int 18 | 19 | class Config: 20 | orm_mode = True # 用于为Pydantic提供配置 21 | 22 | 23 | class UserBase(BaseModel): 24 | email: str 25 | 26 | 27 | class UserCreate(UserBase): 28 | password: str 29 | 30 | 31 | class User(UserBase): 32 | id: int 33 | is_active: bool 34 | items: List[Item] = [] 35 | 36 | class Config: 37 | orm_mode = True 38 | -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/test.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.29_SQLDatabases/FastAPI_No.29_SQLDatabases/test.db -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/test_0/NO.1_yield.py: -------------------------------------------------------------------------------- 1 | """yield的演示""" 2 | 3 | def fun(): 4 | try: 5 | print ('1') 6 | db = 'SessionLocal()' # db也可被赋予变量等 7 | yield db 8 | finally: 9 | print ('3') 10 | 11 | for i in fun(): 12 | print(i) 13 | print('2') 14 | 15 | # fun() -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/test_0/NO.2_db.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from fastapi import Depends, FastAPI, HTTPException 3 | 4 | from sqlalchemy import create_engine 5 | from sqlalchemy.ext.declarative import declarative_base 6 | from sqlalchemy.orm import sessionmaker,Session 7 | from sqlalchemy import Boolean, Column, Integer, String 8 | 9 | """↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 数据库操作初始化 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓""" 10 | SQLALCHEMY_DATABASE_URL = "sqlite:///db_test_1.db" 11 | # SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db" 12 | 13 | engine = create_engine( 14 | SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) 15 | # 仅适用于SQLite。其他数据库不需要。 链接参数:检查同一条线? 即需要可多线程 16 | 17 | # 通过sessionmaker得到一个类,一个能产生session的工厂。 18 | SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) 19 | # 会话生成器 自动提交 自动刷新 20 | Base = declarative_base() # 数据表的结构用 ORM 的语言描述出来 21 | 22 | class M_User(Base): #声明数据库某表的属性与结构 23 | __tablename__ = "users" 24 | 25 | id = Column(Integer, primary_key=True, index=True) # 主键 26 | email = Column(String, unique=True, index=True) 27 | hashed_password = Column(String) 28 | is_active = Column(Boolean, default=True) 29 | 30 | class UserBase(BaseModel): 31 | email: str 32 | 33 | class UserCreate(UserBase): 34 | password: str 35 | 36 | class User(UserBase): 37 | id: int 38 | is_active: bool 39 | class Config: 40 | orm_mode = True 41 | 42 | Base.metadata.create_all(bind=engine) # 到这里就会新建数据库和表(原来没有) 43 | 44 | app = FastAPI() 45 | 46 | """↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 数据库操作(依赖项) ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓""" 47 | def get_db(): 48 | try: 49 | db = SessionLocal() # 这时,才真正产生一个'会话',并且用完要关闭 50 | yield db # 调用该函数将返回generator可迭代对象 51 | finally: 52 | db.close() 53 | print('数据库已关闭') 54 | 55 | 56 | """↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 数据库操作方法 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓""" 57 | # 通过id查询用户信息 58 | def get_user(db: Session, user_id: int): 59 | CCCCCC = db.query(M_User).filter(M_User.id == user_id).first() 60 | print('CCCCCC :', CCCCCC) # 过滤器 61 | return CCCCCC 62 | 63 | 64 | if __name__ == "__main__": 65 | for i in get_db(): 66 | c = get_user(db=i,user_id=2) 67 | print(c.email) 68 | -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/test_0/db_test_1.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.29_SQLDatabases/test_0/db_test_1.db -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/test_1/db_test_1.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from pydantic import BaseModel 3 | from fastapi import Depends, FastAPI, HTTPException 4 | 5 | from sqlalchemy import create_engine 6 | from sqlalchemy.ext.declarative import declarative_base 7 | from sqlalchemy.orm import sessionmaker,Session 8 | from sqlalchemy import Boolean, Column, ForeignKey, Integer, String 9 | from sqlalchemy.orm import relationship 10 | # SELECT * FROM users 11 | 12 | """↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 数据库操作初始化 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓""" 13 | SQLALCHEMY_DATABASE_URL = "sqlite:///db_test_3.db" 14 | # SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db" 15 | 16 | engine = create_engine( 17 | SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}) 18 | # 仅适用于SQLite。其他数据库不需要。 链接参数:检查同一条线? 即需要可多线程 19 | 20 | # 通过sessionmaker得到一个类,一个能产生session的工厂。 21 | SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) 22 | # 会话生成器 自动提交 自动刷新 23 | Base = declarative_base() # 数据表的结构用 ORM 的语言描述出来 24 | 25 | class M_User(Base): #声明数据库某表的属性与结构 26 | __tablename__ = "users" 27 | 28 | id = Column(Integer, primary_key=True, index=True) # 主键 29 | email = Column(String, unique=True, index=True) 30 | hashed_password = Column(String) 31 | is_active = Column(Boolean, default=True) 32 | 33 | class UserBase(BaseModel): 34 | email: str 35 | 36 | class UserCreate(UserBase): 37 | password: str 38 | 39 | class User(UserBase): 40 | id: int 41 | is_active: bool 42 | class Config: 43 | orm_mode = True 44 | 45 | Base.metadata.create_all(bind=engine) 46 | 47 | app = FastAPI() 48 | 49 | """↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 数据库操作(依赖项) ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓""" 50 | def get_db(): 51 | try: 52 | db = SessionLocal() # 这时,才真正产生一个'会话',并且用完要关闭 53 | yield db # 生成器 54 | finally: 55 | db.close() 56 | print('数据库已关闭') 57 | 58 | 59 | """↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 数据库操作方法 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓""" 60 | # 通过id查询用户信息 61 | def get_user(db: Session, user_id: int): 62 | CCCCCC = db.query(M_User).filter(M_User.id == user_id).first() 63 | print(CCCCCC) # 过滤器 64 | return CCCCCC 65 | 66 | # 新建用户(数据库) 67 | def db_create_user(db: Session, user: UserCreate): 68 | fake_hashed_password = user.password + "notreallyhashed" 69 | db_user = M_User(email=user.email, hashed_password=fake_hashed_password) 70 | db.add(db_user) 71 | db.commit() # 提交即保存到数据库 72 | db.refresh(db_user) # 刷新 73 | return db_user 74 | 75 | """↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ post和get请求 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓""" 76 | # 新建用户(post请求) 77 | @app.post("/users/", response_model=User) 78 | def create_user(user: UserCreate, db: Session = Depends(get_db)): 79 | # Depends(get_db)使用依赖关系可防止不同请求意外共享同一链接 80 | return db_create_user(db=db, user=user) 81 | 82 | # 用ID方式读取用户 83 | @app.get("/users/{user_id}", response_model=User) 84 | def read_user(user_id: int, db: Session = Depends(get_db)): 85 | db_user = get_user(db, user_id=user_id) 86 | print(db_user) 87 | if db_user is None: 88 | raise HTTPException(status_code=404, detail="User not found") 89 | 90 | return db_user 91 | 92 | 93 | if __name__ == '__main__': 94 | import uvicorn 95 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.29_SQLDatabases/test_1/db_test_3.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.29_SQLDatabases/test_1/db_test_3.db -------------------------------------------------------------------------------- /FastAPI_No.2_helloworld/FastAPI_No.1_helloworld.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | 4 | app = FastAPI() 5 | 6 | 7 | @app.get("/") 8 | async def main(): 9 | return {"message": "Helloworld,FastAPI"} 10 | 11 | 12 | if __name__ == '__main__': 13 | import uvicorn 14 | uvicorn.run(app, host="127.0.0.1", port=8000) 15 | 16 | 17 | # uvicorn FastAPI_No.1_helloworld.py:app --reload 18 | -------------------------------------------------------------------------------- /FastAPI_No.2_helloworld/FastAPI_No.2_helloworld.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | 4 | app = FastAPI() 5 | 6 | 7 | @app.get("/") 8 | async def main(): 9 | return {"message": "Hello,FastAPI"} 10 | 11 | 12 | if __name__ == '__main__': 13 | import uvicorn 14 | uvicorn.run(app, host="127.0.0.1", port=8000) 15 | 16 | -------------------------------------------------------------------------------- /FastAPI_No.2_helloworld/__pycache__/main.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.2_helloworld/__pycache__/main.cpython-37.pyc -------------------------------------------------------------------------------- /FastAPI_No.2_helloworld/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | app = FastAPI() 4 | 5 | 6 | @app.get("/") 7 | async def root(): 8 | return {"message": "Hello World!!!!"} 9 | -------------------------------------------------------------------------------- /FastAPI_No.30_Bigger_Applications_Multiple_Files/app/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import Depends, FastAPI, Header, HTTPException 2 | 3 | from routers import users,items 4 | # from .routers import items, users 5 | 6 | app = FastAPI() 7 | 8 | async def get_token_header(x_token: str = Header(...)): 9 | if x_token != "fake-super-secret-token": # 假超密令牌 10 | raise HTTPException(status_code=400, detail="X-Token header invalid") # X令牌头无效 11 | 12 | 13 | app.include_router(users.router) 14 | app.include_router(items.router, 15 | # 前缀 16 | prefix="/items", 17 | tags=["items"], 18 | # 依赖关系 19 | dependencies=[Depends(get_token_header)], 20 | responses={404: {"description": "Not found"}}, 21 | ) 22 | 23 | if __name__ == '__main__': 24 | import uvicorn 25 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.30_Bigger_Applications_Multiple_Files/app/routers/__pycache__/items.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.30_Bigger_Applications_Multiple_Files/app/routers/__pycache__/items.cpython-37.pyc -------------------------------------------------------------------------------- /FastAPI_No.30_Bigger_Applications_Multiple_Files/app/routers/__pycache__/users.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.30_Bigger_Applications_Multiple_Files/app/routers/__pycache__/users.cpython-37.pyc -------------------------------------------------------------------------------- /FastAPI_No.30_Bigger_Applications_Multiple_Files/app/routers/items.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, HTTPException 2 | 3 | router = APIRouter() 4 | 5 | 6 | @router.get("/" ) 7 | async def read_items(): 8 | return [{"name": "Item Foo"}, {"name": "item Bar"}] 9 | 10 | 11 | @router.get("/{item_id}") 12 | async def read_item(item_id: str): 13 | return {"name": "Fake Specific Item", "item_id": item_id} 14 | # 伪造特定物品 15 | 16 | @router.put( 17 | "/{item_id}", 18 | tags=["custom"], # custom 习惯 19 | responses={403: {"description": "Operation forbidden"}}, # 禁止操作 20 | ) 21 | async def update_item(item_id: str): 22 | if item_id != "foo": 23 | raise HTTPException(status_code=403, detail="You can only update the item: foo") 24 | return {"item_id": item_id, "name": "The Fighters"} 25 | -------------------------------------------------------------------------------- /FastAPI_No.30_Bigger_Applications_Multiple_Files/app/routers/users.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter 2 | 3 | router = APIRouter() 4 | 5 | 6 | @router.get("/users/", tags=["users"]) 7 | async def read_users(): 8 | return [{"username": "Foo"}, {"username": "Bar"}] 9 | 10 | 11 | @router.get("/users/me", tags=["users"]) 12 | async def read_user_me(): 13 | return {"username": "fakecurrentuser"} 14 | 15 | 16 | @router.get("/users/{username}", tags=["users"]) 17 | async def read_user(username: str): 18 | return {"username": username} 19 | -------------------------------------------------------------------------------- /FastAPI_No.31_Background_Tasks/FastAPI_No.31_Background_Tasks.py: -------------------------------------------------------------------------------- 1 | from fastapi import BackgroundTasks, Depends, FastAPI 2 | 3 | app = FastAPI() 4 | 5 | 6 | def write_log(message: str): 7 | with open("log.txt", mode="a") as log: 8 | log.write(message) 9 | 10 | 11 | def get_query(background_tasks: BackgroundTasks, q: str = None): # , xxx:str = None 12 | if q: 13 | message = f"found query: {q}\n" 14 | # print(xxx) 15 | print('q', id(q)); print(q) 16 | print(type(background_tasks)); print('first', background_tasks) 17 | background_tasks.add_task(write_log, message) 18 | return q 19 | 20 | 21 | @app.post("/send-notification/{email}") 22 | async def send_notification( 23 | email: str, background_tasks: BackgroundTasks, xxx: str = Depends(get_query) 24 | ): 25 | print('xxx', id(xxx));print(xxx) 26 | print(type(background_tasks)); print(background_tasks) 27 | message = f"message to {email}\n" 28 | background_tasks.add_task(write_log, message) 29 | return {"message": "Message sent"} 30 | 31 | 32 | if __name__ == '__main__': 33 | import uvicorn 34 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.31_Background_Tasks/log.txt: -------------------------------------------------------------------------------- 1 | found query: cccccc 2 | message to xxx@ssss.com 3 | found query: cccc 4 | message to xxxx 5 | found query: ggggg 6 | message to ttttttt@ttt.com 7 | found query: ttttt 8 | message to ttttt@tt.com 9 | found query: ttttt 10 | message to ttttt@tt.com 11 | found query: ttttt 12 | message to ttttt@tt.com 13 | found query: xxx 14 | message to xxxxx@xxx.com 15 | found query: xx 16 | message to xxxxxx 17 | found query: rrr 18 | message to rrrrrrr 19 | found query: rrrc 20 | message to rrrrrrrc 21 | found query: rrrc 22 | message to rrrrrrrc 23 | found query: DDDDDD 24 | message to GGGGG@GG.COM 25 | found query: WWW 26 | message to WWWWWW@WWW.COM 27 | -------------------------------------------------------------------------------- /FastAPI_No.32_Application_Configuration/FastAPI_No.32_Application_Configuration.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | # app = FastAPI( 4 | # title="My Super Project", 5 | # description="This is a very fancy project, with auto docs for the API and everything", 6 | # version="6.6.6", 7 | # ) 8 | # app = FastAPI(openapi_url="/api/v1/openapi.json") 9 | app = FastAPI(docs_url="/documentation", redoc_url=None) 10 | 11 | 12 | @app.get("/items/") 13 | async def read_items(): 14 | return [{"name": "Foo"}] 15 | 16 | 17 | if __name__ == '__main__': 18 | import uvicorn 19 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.33_Static_Files/FastAPI_No.33_Static_Files.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI, Form, Depends 3 | from starlette.requests import Request 4 | from starlette.staticfiles import StaticFiles 5 | from starlette.templating import Jinja2Templates 6 | 7 | app = FastAPI() 8 | templates = Jinja2Templates(directory="templates") 9 | app.mount('/static', StaticFiles(directory='static'), name='static') 10 | 11 | 12 | @app.get("/") 13 | async def main(request: Request): 14 | return templates.TemplateResponse('index.html', {'request': request}) 15 | 16 | 17 | 18 | if __name__ == '__main__': 19 | import uvicorn 20 | uvicorn.run(app, host="127.0.0.1", port=8000) 21 | -------------------------------------------------------------------------------- /FastAPI_No.33_Static_Files/static/css/jumbotron.css: -------------------------------------------------------------------------------- 1 | /* Move down content because we have a fixed navbar that is 50px tall */ 2 | body { 3 | padding-top: 50px; 4 | padding-bottom: 20px; 5 | } 6 | -------------------------------------------------------------------------------- /FastAPI_No.33_Static_Files/static/css/signin.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 40px; 3 | padding-bottom: 40px; 4 | background-color: #eee; 5 | } 6 | 7 | .form-signin { 8 | max-width: 330px; 9 | padding: 15px; 10 | margin: 0 auto; 11 | } 12 | .form-signin .form-signin-heading, 13 | .form-signin .checkbox { 14 | margin-bottom: 10px; 15 | } 16 | .form-signin .checkbox { 17 | font-weight: normal; 18 | } 19 | .form-signin .form-control { 20 | position: relative; 21 | height: auto; 22 | -webkit-box-sizing: border-box; 23 | -moz-box-sizing: border-box; 24 | box-sizing: border-box; 25 | padding: 10px; 26 | font-size: 16px; 27 | } 28 | .form-signin .form-control:focus { 29 | z-index: 2; 30 | } 31 | .form-signin input[type="email"] { 32 | margin-bottom: -1px; 33 | border-bottom-right-radius: 0; 34 | border-bottom-left-radius: 0; 35 | } 36 | .form-signin input[type="password"] { 37 | margin-bottom: 10px; 38 | border-top-left-radius: 0; 39 | border-top-right-radius: 0; 40 | } 41 | -------------------------------------------------------------------------------- /FastAPI_No.33_Static_Files/static/imgs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.33_Static_Files/static/imgs/favicon.ico -------------------------------------------------------------------------------- /FastAPI_No.33_Static_Files/static/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2016 Twitter, Inc. 4 | * Licensed under the MIT license 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); -------------------------------------------------------------------------------- /FastAPI_No.33_Static_Files/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Jumbotron Template for Bootstrap 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 39 | 40 | 41 |
42 |
43 |

Hello FastAPI

44 |

This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.

45 |

Learn more »

46 |
47 |
48 | 49 |
50 | 51 |
52 |
53 |

Heading

54 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

55 |

View details »

56 |
57 |
58 |

Heading

59 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

60 |

View details »

61 |
62 |
63 |

Heading

64 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

65 |

View details »

66 |
67 |
68 | 69 |
70 | 71 |
72 |

© 2016 Company, Inc.

73 |
74 |
75 | 76 | 77 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /FastAPI_No.34_Testing/__init__.py: -------------------------------------------------------------------------------- 1 | pass 2 | -------------------------------------------------------------------------------- /FastAPI_No.34_Testing/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | 3 | app = FastAPI() 4 | 5 | 6 | @app.get("/") 7 | async def read_main(): 8 | return {"msg": "Hello World"} 9 | -------------------------------------------------------------------------------- /FastAPI_No.34_Testing/main_b.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI, Header, HTTPException 2 | from pydantic import BaseModel 3 | 4 | fake_secret_token = "coneofsilence" 5 | 6 | fake_db = { 7 | "foo": {"id": "foo", "title": "Foo", "description": "There goes my hero"}, 8 | "bar": {"id": "bar", "title": "Bar", "description": "The bartenders"}, 9 | } 10 | 11 | app = FastAPI() 12 | 13 | 14 | class Item(BaseModel): 15 | id: str 16 | title: str 17 | description: str = None 18 | 19 | 20 | @app.get("/items/{item_id}", response_model=Item) 21 | async def read_main(item_id: str, x_token: str = Header(...)): 22 | if x_token != fake_secret_token: 23 | raise HTTPException(status_code=400, detail="Invalid X-Token header") 24 | if item_id not in fake_db: 25 | raise HTTPException(status_code=404, detail="Item not found") 26 | return fake_db[item_id] 27 | 28 | 29 | @app.post("/items/", response_model=Item) 30 | async def create_item(item: Item, x_token: str = Header(...)): 31 | if x_token != fake_secret_token: 32 | raise HTTPException(status_code=400, detail="Invalid X-Token header") 33 | if item.id in fake_db: 34 | raise HTTPException(status_code=400, detail="Item already exists") 35 | fake_db[item.id] = item 36 | return item 37 | 38 | # if __name__ == '__main__': 39 | # import uvicorn 40 | # uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.34_Testing/test_main.py: -------------------------------------------------------------------------------- 1 | from starlette.testclient import TestClient 2 | 3 | # from .main import app 4 | from main import app 5 | 6 | client = TestClient(app) 7 | 8 | 9 | def test_read_main(): 10 | response = client.get("/") 11 | assert response.status_code == 200 12 | assert response.json() == {"msg": "Hello World"} 13 | 14 | # 等价于 15 | # if not expression: 16 | # raise AssertionError 17 | 18 | 19 | 20 | # if __name__ == '__main__': 21 | # import uvicorn 22 | # uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.34_Testing/test_main_b.py: -------------------------------------------------------------------------------- 1 | from starlette.testclient import TestClient 2 | 3 | from main_b import app 4 | # from .main_b import app 5 | 6 | client = TestClient(app) 7 | 8 | 9 | def test_read_item(): 10 | response = client.get("/items/foo", headers={"X-Token": "coneofsilence"}) 11 | assert response.status_code == 200 12 | assert response.json() == { 13 | "id": "foo", 14 | "title": "Foo", 15 | "description": "There goes my hero", 16 | } 17 | 18 | 19 | def test_read_item_bad_token(): 20 | response = client.get("/items/foo", headers={"X-Token": "hailhydra"}) 21 | assert response.status_code == 400 22 | assert response.json() == {"detail": "Invalid X-Token header"} 23 | 24 | 25 | def test_read_inexistent_item(): 26 | response = client.get("/items/baz", headers={"X-Token": "coneofsilence"}) 27 | assert response.status_code == 404 28 | assert response.json() == {"detail": "Item not found"} 29 | 30 | 31 | def test_create_item(): 32 | response = client.post( 33 | "/items/", 34 | headers={"X-Token": "coneofsilence"}, 35 | json={"id": "foobar", "title": "Foo Bar", "description": "The Foo Barters"}, 36 | ) 37 | assert response.status_code == 200 38 | assert response.json() == { 39 | "id": "foobar", 40 | "title": "Foo Bar", 41 | "description": "The Foo Barters", 42 | } 43 | 44 | 45 | def test_create_item_bad_token(): 46 | response = client.post( 47 | "/items/", 48 | headers={"X-Token": "hailhydra"}, 49 | json={"id": "bazz", "title": "Bazz", "description": "Drop the bazz"}, 50 | ) 51 | assert response.status_code == 400 52 | assert response.json() == {"detail": "Invalid X-Token header"} 53 | 54 | 55 | def test_create_existing_token(): 56 | response = client.post( 57 | "/items/", 58 | headers={"X-Token": "coneofsilence"}, 59 | json={ 60 | "id": "foo", 61 | "title": "The Foo ID Stealers", 62 | "description": "There goes my stealer", 63 | }, 64 | ) 65 | assert response.status_code == 400 66 | assert response.json() == {"detail": "Item already exists"} 67 | 68 | 69 | 70 | # if __name__ == '__main__': 71 | # import uvicorn 72 | # uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.35_Debugging/FastAPI_No.35_Debugging.py: -------------------------------------------------------------------------------- 1 | 2 | from fastapi import FastAPI 3 | 4 | app = FastAPI() 5 | 6 | 7 | @app.get("/") 8 | def root(): 9 | a = "a" 10 | b = "b" + a 11 | return {"hello world": b} 12 | 13 | 14 | if __name__ == "__main__": 15 | import uvicorn 16 | uvicorn.run(app, host="0.0.0.0", port=8000) 17 | 18 | -------------------------------------------------------------------------------- /FastAPI_No.3_templates/FastAPI_No.2_templates.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from starlette.requests import Request 3 | from fastapi import FastAPI 4 | from starlette.templating import Jinja2Templates 5 | 6 | app = FastAPI() 7 | templates = Jinja2Templates(directory="templates") 8 | 9 | @app.get("/") 10 | async def main(request: Request): 11 | return templates.TemplateResponse('index.html', {'request': request, 'hello': 'HI...'}) 12 | 13 | @app.get("/{item_id}/") 14 | async def item_id(request: Request, item_id): 15 | return templates.TemplateResponse('index.html', {'request': request, "item_id": item_id}) 16 | 17 | 18 | if __name__ == '__main__': 19 | import uvicorn 20 | uvicorn.run(app, host="127.0.0.1", port=8000) 21 | 22 | 23 | # uvicorn FastAPI_No.1_helloworld.py:app --reload 24 | -------------------------------------------------------------------------------- /FastAPI_No.3_templates/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 |

HELLO FastAPI...

3 |

{{ hello }}

4 |

{{ item_id }}

5 | -------------------------------------------------------------------------------- /FastAPI_No.4_form/post_test_5.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from starlette.requests import Request 3 | from fastapi import FastAPI, Form 4 | from starlette.templating import Jinja2Templates 5 | 6 | app = FastAPI() 7 | templates = Jinja2Templates(directory="templates") 8 | 9 | 10 | @app.post("/user/") 11 | async def form_text(request: Request, username: str = Form(...), password: str = Form(...)): 12 | 13 | print('username',username) 14 | print('password',password) 15 | 16 | # return {'text_1':text_1 , 'text_2': text_2} 17 | return templates.TemplateResponse('index.html', {'request': request, 'username': username, 'password': password}) 18 | 19 | 20 | @app.get("/") 21 | async def main(request: Request): 22 | return templates.TemplateResponse('post.html', {'request': request}) 23 | 24 | if __name__ == '__main__': 25 | import uvicorn 26 | uvicorn.run(app, host="127.0.0.1", port=8000) 27 | -------------------------------------------------------------------------------- /FastAPI_No.4_form/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Signin Template for Bootstrap 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 |

HELLO..{{ username }}

28 |

HELLO..{{ password }}

29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /FastAPI_No.4_form/templates/post.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | 6 |
7 | 8 |
9 | 10 |
11 | 12 |

13 | 14 |
15 | 16 |
17 | -------------------------------------------------------------------------------- /FastAPI_No.5_file/post_test_5.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from typing import List 3 | from starlette.requests import Request 4 | from fastapi import FastAPI, Form, File, UploadFile 5 | from starlette.templating import Jinja2Templates 6 | 7 | app = FastAPI() 8 | templates = Jinja2Templates(directory="templates") 9 | 10 | 11 | @app.post("/files/") 12 | async def files( 13 | request: Request, 14 | files_list: List[bytes] = File(...), 15 | files_name: List[UploadFile] = File(...), 16 | ): 17 | return templates.TemplateResponse("index.html", 18 | { 19 | "request": request, 20 | "file_sizes": [len(file) for file in files_list], 21 | "filenames": [file.filename for file in files_name], 22 | }) 23 | 24 | 25 | @app.post("/create_file/") 26 | async def create_file( 27 | request: Request, 28 | file: bytes = File(...), 29 | fileb: UploadFile = File(...), 30 | notes: str = Form(...), 31 | ): 32 | return templates.TemplateResponse("index.html", 33 | { 34 | "request": request, 35 | "file_size": len(file), 36 | "notes": notes, 37 | "fileb_content_type": fileb.content_type, 38 | }) 39 | 40 | 41 | @app.get("/") 42 | async def main(request: Request): 43 | return templates.TemplateResponse('post.html', {'request': request}) 44 | 45 | 46 | if __name__ == '__main__': 47 | import uvicorn 48 | uvicorn.run(app, host="127.0.0.1", port=8000) 49 | -------------------------------------------------------------------------------- /FastAPI_No.5_file/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |

NO.1

27 |

File Name:{{ filenames }}

28 |

File Size:{{ file_sizes }}

29 | 30 |

NO.2

31 |

File Size:{{ file_size }}

32 |

File Notes:{{ notes }}

33 |

File Type:{{ fileb_content_type }}

34 |
35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /FastAPI_No.5_file/templates/post.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

4 |

5 | 6 |
7 |


8 | 9 | 10 |
11 |

12 |

13 |

14 | 15 |
16 | 17 | -------------------------------------------------------------------------------- /FastAPI_No.6_bootstrap_static/post_test_5.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI, Form 3 | from starlette.requests import Request 4 | from starlette.staticfiles import StaticFiles 5 | from starlette.templating import Jinja2Templates 6 | 7 | app = FastAPI() 8 | templates = Jinja2Templates(directory="templates") 9 | app.mount('/static', StaticFiles(directory='static'), name='static') 10 | 11 | 12 | @app.post("/user/") 13 | async def files( 14 | request: Request, 15 | username: str = Form(...), 16 | password: str = Form(...), 17 | ): 18 | print('username', username) 19 | print('password', password) 20 | return templates.TemplateResponse( 21 | 'index.html', 22 | { 23 | 'request': request, 24 | 'username': username, 25 | } 26 | ) 27 | 28 | 29 | @app.get("/") 30 | async def main(request: Request): 31 | return templates.TemplateResponse('signin.html', {'request': request}) 32 | 33 | 34 | 35 | if __name__ == '__main__': 36 | import uvicorn 37 | uvicorn.run(app, host="127.0.0.1", port=8000) 38 | -------------------------------------------------------------------------------- /FastAPI_No.6_bootstrap_static/static/css/jumbotron.css: -------------------------------------------------------------------------------- 1 | /* Move down content because we have a fixed navbar that is 50px tall */ 2 | body { 3 | padding-top: 50px; 4 | padding-bottom: 20px; 5 | } 6 | -------------------------------------------------------------------------------- /FastAPI_No.6_bootstrap_static/static/css/signin.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 40px; 3 | padding-bottom: 40px; 4 | background-color: #eee; 5 | } 6 | 7 | .form-signin { 8 | max-width: 330px; 9 | padding: 15px; 10 | margin: 0 auto; 11 | } 12 | .form-signin .form-signin-heading, 13 | .form-signin .checkbox { 14 | margin-bottom: 10px; 15 | } 16 | .form-signin .checkbox { 17 | font-weight: normal; 18 | } 19 | .form-signin .form-control { 20 | position: relative; 21 | height: auto; 22 | -webkit-box-sizing: border-box; 23 | -moz-box-sizing: border-box; 24 | box-sizing: border-box; 25 | padding: 10px; 26 | font-size: 16px; 27 | } 28 | .form-signin .form-control:focus { 29 | z-index: 2; 30 | } 31 | .form-signin input[type="email"] { 32 | margin-bottom: -1px; 33 | border-bottom-right-radius: 0; 34 | border-bottom-left-radius: 0; 35 | } 36 | .form-signin input[type="password"] { 37 | margin-bottom: 10px; 38 | border-top-left-radius: 0; 39 | border-top-right-radius: 0; 40 | } 41 | -------------------------------------------------------------------------------- /FastAPI_No.6_bootstrap_static/static/imgs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/FastAPI_No.6_bootstrap_static/static/imgs/favicon.ico -------------------------------------------------------------------------------- /FastAPI_No.6_bootstrap_static/static/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2016 Twitter, Inc. 4 | * Licensed under the MIT license 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); -------------------------------------------------------------------------------- /FastAPI_No.6_bootstrap_static/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Jumbotron Template for Bootstrap 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 50 | 51 | 52 |
53 |
54 |

Hello, {{ username }}

55 |

This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.

56 |

Learn more »

57 |
58 |
59 | 60 |
61 | 62 |
63 |
64 |

Heading

65 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

66 |

View details »

67 |
68 |
69 |

Heading

70 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

71 |

View details »

72 |
73 |
74 |

Heading

75 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

76 |

View details »

77 |
78 |
79 | 80 |
81 | 82 |
83 |

© 2016 Company, Inc.

84 |
85 |
86 | 87 | 88 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /FastAPI_No.6_bootstrap_static/templates/signin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Signin Template for Bootstrap 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 41 | 42 |
43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /FastAPI_No.7_Path_Parameters/FastAPI_No.7_Path_Parameters_1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | 4 | app = FastAPI() 5 | 6 | @app.get("/me/xx") 7 | async def read_item_me(): 8 | return {"me": 'me'} 9 | 10 | @app.get("/me/{item_id}") 11 | async def read_item(item_id: str): 12 | return {"item_id": item_id} 13 | 14 | 15 | @app.get("/") 16 | async def main(): 17 | return {"message": "Hello,FastAPI"} 18 | 19 | 20 | 21 | if __name__ == '__main__': 22 | import uvicorn 23 | uvicorn.run(app, host="127.0.0.1", port=8000) 24 | 25 | -------------------------------------------------------------------------------- /FastAPI_No.7_Path_Parameters/FastAPI_No.7_Path_Parameters_2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from enum import Enum 4 | 5 | class Name(str, Enum): 6 | Allan = '张三' 7 | Jon = '李四' 8 | Bob = '王五' 9 | 10 | app = FastAPI() 11 | 12 | 13 | @app.get("/{who}") 14 | async def get_day(who: Name): 15 | if who == Name.Allan: 16 | return {"who": who, "message": "张三是德国人"} 17 | if who.value == '李四': 18 | return {"who": who, "message": "李四是英国人"} 19 | return {"who": who, "message": "王五是法国人"} 20 | 21 | 22 | @app.get("/") 23 | async def main(): 24 | return {"message": "Hello,FastAPI"} 25 | 26 | 27 | 28 | if __name__ == '__main__': 29 | import uvicorn 30 | uvicorn.run(app, host="127.0.0.1", port=8000) -------------------------------------------------------------------------------- /FastAPI_No.8_Query_Parameters/FastAPI_No.8_Query_Parameters.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | 4 | app = FastAPI() 5 | fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}] 6 | 7 | @app.get("/items/") 8 | async def read_item(skip: int = 0, limit: int = 10): 9 | return fake_items_db[skip : skip + limit] 10 | 11 | @app.get("/i/") 12 | async def i(A: str = 'HI..', B: str = 'Hello..', C: str = 'He..'): 13 | return {'cc': A+B+C},{'dd': B+C} 14 | 15 | @app.get("/ii/") 16 | async def ii(A: int = 0, B: int = 10, C: int = 20): 17 | return {'cc': A+B+C},{'dd': B+C} 18 | 19 | @app.get("/iii/") 20 | async def iii(A: int = 0, B: int = 10, C: int = 20): 21 | return 'A+B+C',A+B+C 22 | 23 | # bool与类型转换 24 | @app.get("/xxx/{item_id}") 25 | async def xxx(item_id: str, QQ: str = None, SS: bool = False): 26 | item = {"item_id": item_id} 27 | if QQ: 28 | item.update({"QQ": QQ}) 29 | if not SS: # 如果SS是假 30 | item.update( 31 | {"item_id": "This is SSSSSSS"} 32 | ) 33 | return item 34 | 35 | #多路径 和 查询参数 和 必填字段 36 | @app.get("/user/{user_id}/item/{item_id}") 37 | async def read_user_item( 38 | user_id: int, item_id: str, q: str = None, short: bool = False 39 | ): 40 | item = {"item_id": item_id, "owner_id": user_id} 41 | if q: 42 | item.update({"q": q}) 43 | if not short: 44 | item.update( 45 | {"description": "This is an amazing item that has a long description"} 46 | ) 47 | return item 48 | 49 | 50 | if __name__ == '__main__': 51 | import uvicorn 52 | uvicorn.run(app, host="127.0.0.1", port=8000) 53 | 54 | -------------------------------------------------------------------------------- /FastAPI_No.9_Request_Body/FastAPI_No.9_Request_Body.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | from fastapi import FastAPI 3 | from pydantic import BaseModel 4 | 5 | 6 | class Item(BaseModel): 7 | name: str 8 | description: str = None 9 | price: float 10 | tax: float = None 11 | 12 | app = FastAPI() 13 | 14 | @app.post("/items/") 15 | async def create_item(item: Item): 16 | print(item.dict()) 17 | return item,'人生没有无意义的经历。' 18 | 19 | @app.put("/items/{item_id}") 20 | async def create_item2(item_id: int, item: Item, q: str = None): 21 | result = {"item_id": item_id, **item.dict()} 22 | if q: 23 | result.update({"q": q}) 24 | print(result) 25 | return result 26 | 27 | 28 | if __name__ == '__main__': 29 | import uvicorn 30 | uvicorn.run(app, host="127.0.0.1", port=8000) 31 | 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [视频教学地址](https://space.bilibili.com/396891097) 2 | ## 中文学习教程 3 | - 1、本教程每一个案例都可以独立跑,前提是安装好依赖包。 4 | - 2、本教程并未按照官方教程顺序,而是按照实际使用顺序编排。 5 | 6 | # [Video Teaching Address](https://space.bilibili.com/396891097) 7 | ## FastAPI Learning Example 8 | - 1.Each case in this tutorial can run independently, provided that the dependency package is installed. 9 | - 2.This tutorial is not in the order of official tutorials, but in the order of actual use. 10 | 11 | -------------------------------------------------------------------------------- /win_from_import_err.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oinsd/FastAPI-Learning-Example/32969fb0a5468934b241883d05e5e4dc2e54a6a9/win_from_import_err.zip --------------------------------------------------------------------------------