├── .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 | 点我发送ajax
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 |
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 |
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 |
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 |
27 |
28 |
37 |
38 |
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 |
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 |
7 |
8 |
9 |
10 |
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 |
27 |
28 |
37 |
48 |
49 |
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 |
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
--------------------------------------------------------------------------------