# FastAPI APIRoute() 應用實作 - *Route in Large System*
###### tags: `backend`
Copyright 2021, [月下麒麟](https://hackmd.io/@YMont/note-catalog)
---
## Target
>查爾斯成立的公司已邁入第10年,隨著公司組織的擴張
>不得不想個辦法,為賺錢部門裁切出去成為一個獨立的公司
>否則,這營運、經營起來的難度,已超出查爾斯當年的預期
>這令他白髮掉滿地...
==今天會說明關於URL與Route的應用==
(咦 Route是什麼!?)
## Concept
舉個實例[顏氏牧場](https://yenpasture.com/pasture1/scene.php)來說 (單純覺得它網頁做得很漂亮 作為引用,沒有業配也沒有工商XD)
牧場主頁,裡面依序有五個分頁(理念、食宿、預約、風情、前往)
```
https://yenpasture.com/pasture1
```

<br>
牧場理念
```
https://yenpasture.com/pasture1/about.php
```

<br>
露營食宿
```
https://yenpasture.com/pasture1/camp.php
```

<br>
其他分頁以此類推,就不繼續列舉
是否有發現一個規律呢
**觀察1**
我再把這幾個URL放在一起 觀察看看
```
https://yenpasture.com/pasture1
https://yenpasture.com/pasture1/about.php
https://yenpasture.com/pasture1/camp.php
https://yenpasture.com/pasture1/scene.php
https://yenpasture.com/pasture1/map.php
```
在主結構pasture1下,有四個分頁,依序為about, camp, scene, map
對應到UI的畫面,當然使用者就能一目了然這幾個分頁的功能
再對應到後端的開發、管理,做好切分分類的工作後,未來無論是修改或是擴增,絕對都會很方便操作。
**觀察2**
如果你具備強烈的好奇心,你可能會跟我一樣想**有pasture1**,那是不是也會有**pasture2呢**
沒錯,筆者當時也是這樣思考的
```
https://www.yenpasture.com/pasture2 #這個會出現404 not found
https://www.yenpasture.com/pasture2/ #這個會redirect Website Expired
```
但遺憾的是開發者並沒有這樣想 ~~可惡 猜錯了~~
不過,*這樣觀察會發現,它網頁原本應該還是架在pasture2的XD*
<br>
**觀察3**
推測它的2應該有變更過啦XD
或許跟他的中文命名有相關,但是1也沒有再回頭重新修改了(茶~)

```
https://www.yenpasture2.com/workshop # 牧場2在這裡
```
<br>
```typescript=
|--yenpasture/
|--yenpasture/pasture1/
| |--yenpasture/pasture1/about.php
| |--yenpasture/pasture1/camp.php
| |--yenpasture/pasture1/booking.php
| |--yenpasture/pasture1/scene.php
| |--yenpasture/pasture1/map.php
|
|--yenpasture2/pasture/
| |--yenpasture2/pasture/events
| |--yenpasture2/pasture/shop
| |--yenpasture2/pasture/photography
| |--yenpasture2/pasture/picnic
| |--yenpasture2/pasture/party
| |--yenpasture2/pasture/2021-marketing
| |--yenpasture2/pasture/about
```
URL就不多加解釋啦
至於Route在中文上會稱作**路由**,可以把它理解成一種URL切換的過程(路徑)
Route是後端再切分邏輯做使用的
==白話來說,當你網頁畫面**點擊顏氏牧場1的關於**,
故後端需要把yenpasture/pasture1/about這段URL,
做**切換**到這個位置(顏氏牧場1的關於)==
---
## Implement
廢話不多說,讓我們進行實作吧!
### Directory Achitecture
```typescript=
|--app
|--__init__.py
|--main.py
|
|--\route1
| |--__init__.py
| |--router1.py
|
|--\route2
|--__init__.py
|--router2.py
```
### URLs Achitecture
當然,你也可以把結構寫成這個樣子
```typescript=
|--127.0.0.1:8001/
|--127.0.0.1:8001/router
|--127.0.0.1:8001/router/1
|--127.0.0.1:8001/router/2
```
<br>
底下的架構,主要是想讓router1跟router2是平行關係的
至於上例好,還是下例好,就不在本次的討論範圍
主要==要展示如何使用FastAPI的 APIRouter的功能==
```typescript=
|--127.0.0.1:8001/
|--127.0.0.1:8001/router1
|--127.0.0.1:8001/router2
```
<br>
另一精神是為了==解決資料夾分層結構==的問題
當撰寫的系統日趨龐大,勢必就會遇到程式分類的問題
那為了避免Python在import來 import去的,導致產生import loop與route錯誤的問題
故就來使用這方便的工具吧
### Code-router1
```python=
# router1.py
from fastapi import FastAPI, APIRouter, HTTPException
router = APIRouter() # point!
@router.get("/router1")
def router1() -> dict:
return {"msg":"Hello Router1"}
```
### Code-router2
```python=
# router2.py
from fastapi import FastAPI, APIRouter, HTTPException
router = APIRouter() # point!
@router.get("/router2")
def router1() -> dict:
return {"msg":"Hello Router2"}
```
### Code-main
```python=
from fastapi import FastAPI, APIRouter, HTTPException
# 將route1、2資料夾內的router1、2 python檔引入
from route1 import router1
from route2 import router2
app = FastAPI() # 以app作為FastAPI實例
api_router = APIRouter() # 以api_router作為APIRouter實例,本次重點!
api_router.include_router(router1.router) # 把router1檔案裡的路由結合進api_router
api_router.include_router(router2.router) # 把router2檔案裡的路由結合進api_router
@api_router.get("/")
def root() -> dict:
"""
Root Get
"""
return {"msg":"Hello root"}
app.include_router(api_router) # app實例將api_router的路由結合進去
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8001)
```
執行後,成果如下


<br>


<br>


<br>
## Reference
[FastAPI Bigger Applications - Multiple Files¶](https://fastapi.tiangolo.com/tutorial/bigger-applications/)
## Supplement
**1**
這個功能就類似於flask的**Blueprints**
>If you come from Flask, this would be the equivalent of Flask's Blueprints.
**2**
你可能會擔心切換路由,會產生網路效能的問題,進而造成delay
>You don't have to worry about performance when including routers.
This will take microseconds and will only happen at startup.
So it won't affect performance. ⚡
## Summary
滿強大的一個功能,使用起來也很方便操作
希望有幫助到你的學習