๐ ๐ฉโ๐ป¶
FastAPI โ๏ธ ๐ ๐ ๐ง, ๐ ๐ค ๐ง ๐ โฎ๏ธ ๐ ๐งฐ, ๐ ๐ง ๐ ๏ธ ๐ฉบ (๐ ๐ฆ ๐).
1๏ธโฃ ๐ฏ ๐ ๐ ๐ซ ๐ฏ โญ ๐ ๐ ๐ช ๐ ๐ฉโ๐ป (๐ฃ ๐ค ๐ฑ ) ๐ ๐ ๏ธ, ๐ ๐ ๐ ๏ธ ๐ช๐ธ.
๐ ๐ฉโ๐ป ๐¶
๐ค ๐ ๐งฐ ๐ ๐ฉโ๐ป โช๏ธโก๏ธ ๐.
โ ๐งฐ ๐ ๐.
๐ฅ ๐ ๐ ๐ธ, ๐ถ ๐ ๐ ๐-๐-๐ฆ๐ช.
๐ ๐ ๐ธ ๐ฉโ๐ป¶
โก๏ธ โถ๏ธ โฎ๏ธ ๐ FastAPI ๐ธ:
from typing import List
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
class ResponseMessage(BaseModel):
message: str
@app.post("/items/", response_model=ResponseMessage)
async def create_item(item: Item):
return {"message": "item received"}
@app.get("/items/", response_model=List[Item])
async def get_items():
return [
{"name": "Plumbus", "price": 3},
{"name": "Portal Gun", "price": 9001},
]
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
class ResponseMessage(BaseModel):
message: str
@app.post("/items/", response_model=ResponseMessage)
async def create_item(item: Item):
return {"message": "item received"}
@app.get("/items/", response_model=list[Item])
async def get_items():
return [
{"name": "Plumbus", "price": 3},
{"name": "Portal Gun", "price": 9001},
]
๐ ๐ โก ๐ ๏ธ ๐ฌ ๐ท ๐ซ โ๏ธ ๐จ ๐ & ๐จ ๐, โ๏ธ ๐ท Item
& ResponseMessage
.
๐ ๏ธ ๐ฉบ¶
๐ฅ ๐ ๐ถ ๐ ๏ธ ๐ฉบ, ๐ ๐ ๐ ๐ โซ๏ธ โ๏ธ ๐ ๐ ๐จ ๐จ & ๐จ ๐จ:
๐ ๐ช ๐ ๐ ๐ โฉ๏ธ ๐ซ ๐ฃ โฎ๏ธ ๐ท ๐ฑ.
๐ โน ๐ช ๐ฑ ๐ ๐, & โคด๏ธ ๐ฆ ๐ ๏ธ ๐ฉบ (๐ฆ ๐).
& ๐ ๐ โน โช๏ธโก๏ธ ๐ท ๐ ๐ ๐ โซ๏ธโ ๐ช โ๏ธ ๐ ๐ฉโ๐ป ๐.
๐ ๐ ๐ฉโ๐ป¶
๐ ๐ ๐ฅ โ๏ธ ๐ฑ โฎ๏ธ ๐ท, ๐ฅ ๐ช ๐ ๐ฉโ๐ป ๐ ๐ธ.
โ openapi-typescript-codegen
¶
๐ ๐ช โ openapi-typescript-codegen
๐ ๐ธ ๐ โฎ๏ธ:
$ npm install openapi-typescript-codegen --save-dev
---> 100%
๐ ๐ฉโ๐ป ๐¶
๐ ๐ฉโ๐ป ๐ ๐ ๐ช โ๏ธ ๐ โธ ๐ธ openapi
๐ ๐ ๐ โ.
โฉ๏ธ โซ๏ธ โ ๐ง๐ฟ ๐, ๐ ๐ฒ ๐ซ๐ ๐ช ๐ค ๐ ๐ ๐, โ๏ธ ๐ ๐ ๐ฎ โซ๏ธ ๐ ๐ package.json
๐.
โซ๏ธ ๐ช ๐ ๐ ๐:
{
"name": "frontend-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"generate-client": "openapi --input http://localhost:8000/openapi.json --output ./src/client --client axios"
},
"author": "",
"license": "",
"devDependencies": {
"openapi-typescript-codegen": "^0.20.1",
"typescript": "^4.6.2"
}
}
โฎ๏ธ โ๏ธ ๐ โ generate-client
โ ๐ค, ๐ ๐ช ๐ โซ๏ธ โฎ๏ธ:
$ npm run generate-client
frontend-app@1.0.0 generate-client /home/user/code/frontend-app
> openapi --input http://localhost:8000/openapi.json --output ./src/client --client axios
๐ ๐ ๐ ๐ ๐ ./src/client
& ๐ โ๏ธ axios
(๐ธ ๐บ๐ธ๐ ๐) ๐.
๐ ๐ ๐ฉโ๐ป ๐¶
๐ ๐ ๐ช ๐ & โ๏ธ ๐ฉโ๐ป ๐, โซ๏ธ ๐ช ๐ ๐ ๐, ๐ ๐ ๐ ๐ค โ ๐ฉโ๐ฌ:
๐ ๐ ๐ค โ ๐ ๐จ:
Tip
๐ โ name
& price
, ๐ ๐ฌ FastAPI ๐ธ, Item
๐ท.
๐ ๐ โ๏ธ โธ โ ๐ ๐ ๐ ๐จ:
๐จ ๐ ๐ โ๏ธ โ:
FastAPI ๐ฑ โฎ๏ธ ๐¶
๐ ๐ผ ๐ FastAPI ๐ฑ ๐ ๐ฆ, & ๐ ๐ ๐ฒ โ๏ธ ๐ ๐ ๐ ๐ช โก ๐ ๏ธ.
๐ผ, ๐ ๐ช โ๏ธ ๐ ๐ฌ & โ1๏ธโฃ ๐ ๐ฉโ๐ป, & ๐ซ ๐ช ๐ฝ ๐:
from typing import List
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
class ResponseMessage(BaseModel):
message: str
class User(BaseModel):
username: str
email: str
@app.post("/items/", response_model=ResponseMessage, tags=["items"])
async def create_item(item: Item):
return {"message": "Item received"}
@app.get("/items/", response_model=List[Item], tags=["items"])
async def get_items():
return [
{"name": "Plumbus", "price": 3},
{"name": "Portal Gun", "price": 9001},
]
@app.post("/users/", response_model=ResponseMessage, tags=["users"])
async def create_user(user: User):
return {"message": "User received"}
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
class ResponseMessage(BaseModel):
message: str
class User(BaseModel):
username: str
email: str
@app.post("/items/", response_model=ResponseMessage, tags=["items"])
async def create_item(item: Item):
return {"message": "Item received"}
@app.get("/items/", response_model=list[Item], tags=["items"])
async def get_items():
return [
{"name": "Plumbus", "price": 3},
{"name": "Portal Gun", "price": 9001},
]
@app.post("/users/", response_model=ResponseMessage, tags=["users"])
async def create_user(user: User):
return {"message": "User received"}
๐ ๐ ๐ฉโ๐ป โฎ๏ธ ๐¶
๐ฅ ๐ ๐ ๐ฉโ๐ป FastAPI ๐ฑ โ๏ธ ๐, โซ๏ธ ๐ ๐ ๐ ๐ฉโ๐ป ๐ โ๏ธ ๐ ๐.
๐ ๐ ๐ ๐ ๐ช โ๏ธ ๐ โ & ๐ช โ ๐ฉโ๐ป ๐:
๐ ๐ผ ๐ โ๏ธ:
ItemsService
UsersService
๐ฉโ๐ป ๐ฉโ๐ฌ ๐¶
โถ๏ธ๏ธ ๐ ๐ ๐ฉโ๐ฌ ๐ ๐ createItemItemsPost
๐ซ ๐ ๐ถ ๐งน:
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
...๐ โฉ๏ธ ๐ฉโ๐ป ๐ โ๏ธ ๐ ๐ ๐ ๏ธ ๐ ๐ โก ๐ ๏ธ.
๐ ๐ ๐ ๐ ๐ ๏ธ ๐ ๐ ๐คญ ๐ โก ๐ ๏ธ, FastAPI โ๏ธ ๐ข ๐, โก, & ๐บ๐ธ๐ ๐ฉโ๐ฌ/๐ ๏ธ ๐ ๐ ๐ ๏ธ ๐, โฉ๏ธ ๐ ๐ โซ๏ธ ๐ช โ ๐ญ ๐ ๐ ๏ธ ๐ ๐.
โ๏ธ ๐ค ๐ ๐ฆ ๐ โ ๐ ๐ โญ. ๐ถ
๐ ๐ ๏ธ ๐ & ๐ ๐ฉโ๐ฌ ๐¶
๐ ๐ช ๐ ๐ ๐ซ ๐ ๏ธ ๐ ๐ โ ๐ซ ๐ & โ๏ธ ๐ ๐ฉโ๐ฌ ๐ ๐ฉโ๐ป.
๐ ๐ผ ๐ ๐ โ๏ธ ๐ ๐ ๐ ๐ ๏ธ ๐ ๐ ๐ ๐.
๐ผ, ๐ ๐ช โ ๐ญ ๐ ๐ โก ๐ ๏ธ โ๏ธ ๐, & โคด๏ธ ๐ ๐ ๏ธ ๐ โ๏ธ ๐ ๐ & โก ๐ ๏ธ ๐ (๐ข ๐).
๐ ๐ ๐ ๐ ๐ข¶
FastAPI โ๏ธ ๐ ๐ ๐ โก ๐ ๏ธ, โซ๏ธ โ๏ธ ๐ ๏ธ ๐ & ๐ ๐ ๐ช ๐ ๐ท, ๐จ โ๏ธ ๐จ.
๐ ๐ช ๐ ๐ ๐ข. โซ๏ธ โ APIRoute
& ๐ข ๐ป.
๐ผ, ๐ฅ โซ๏ธ โ๏ธ ๐ฅ ๐ (๐ ๐ ๐ฒ โ๏ธ ๐ด 1๏ธโฃ ๐) & โก ๐ ๏ธ ๐ (๐ข ๐).
๐ ๐ช โคด๏ธ ๐ถโโ๏ธ ๐ ๐ ๐ข FastAPI generate_unique_id_function
๐ข:
from typing import List
from fastapi import FastAPI
from fastapi.routing import APIRoute
from pydantic import BaseModel
def custom_generate_unique_id(route: APIRoute):
return f"{route.tags[0]}-{route.name}"
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
class Item(BaseModel):
name: str
price: float
class ResponseMessage(BaseModel):
message: str
class User(BaseModel):
username: str
email: str
@app.post("/items/", response_model=ResponseMessage, tags=["items"])
async def create_item(item: Item):
return {"message": "Item received"}
@app.get("/items/", response_model=List[Item], tags=["items"])
async def get_items():
return [
{"name": "Plumbus", "price": 3},
{"name": "Portal Gun", "price": 9001},
]
@app.post("/users/", response_model=ResponseMessage, tags=["users"])
async def create_user(user: User):
return {"message": "User received"}
from fastapi import FastAPI
from fastapi.routing import APIRoute
from pydantic import BaseModel
def custom_generate_unique_id(route: APIRoute):
return f"{route.tags[0]}-{route.name}"
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
class Item(BaseModel):
name: str
price: float
class ResponseMessage(BaseModel):
message: str
class User(BaseModel):
username: str
email: str
@app.post("/items/", response_model=ResponseMessage, tags=["items"])
async def create_item(item: Item):
return {"message": "Item received"}
@app.get("/items/", response_model=list[Item], tags=["items"])
async def get_items():
return [
{"name": "Plumbus", "price": 3},
{"name": "Portal Gun", "price": 9001},
]
@app.post("/users/", response_model=ResponseMessage, tags=["users"])
async def create_user(user: User):
return {"message": "User received"}
๐ ๐ ๐ฉโ๐ป โฎ๏ธ ๐ ๐ ๏ธ ๐¶
๐ ๐ฅ ๐ ๐ ๐ฉโ๐ป ๐, ๐ ๐ ๐ ๐ โซ๏ธ โ๏ธ ๐ ๐ฉโ๐ฌ ๐:
๐ ๐, ๐ฉโ๐ฌ ๐ ๐ โ๏ธ ๐ & โคด๏ธ ๐ข ๐, ๐ ๐ซ ๐ซ ๐ โน โช๏ธโก๏ธ ๐ โก & ๐บ๐ธ๐ ๐ ๏ธ.
๐ ๐ ๐ง ๐ฉโ๐ป ๐¶
๐ ๐ โ๏ธ โ โน.
๐ฅ โช ๐ญ ๐ ๐ ๐ฉโ๐ฌ ๐ ๐ฌ โฉ๏ธ ๐ ๐ค ItemsService
(โ โช๏ธโก๏ธ ๐), โ๏ธ ๐ฅ โ๏ธ ๐ ๐ก ๐ฉโ๐ฌ ๐ ๐โโ๏ธ. ๐ถ
๐ฅ ๐ ๐ฒ ๐ ๐ง โซ๏ธ ๐ ๐ข, ๐ ๐ ๐ ๐ ๐ ๏ธ ๐ ๐.
โ๏ธ ๐ ๐ฉโ๐ป ๐ฅ ๐ช ๐ ๐ ๐ ๏ธ ๐ โถ๏ธ๏ธ โญ ๐ญ ๐ฉโ๐ป, โ ๐ ๐ฉโ๐ฌ ๐ ๐ & ๐งน.
๐ฅ ๐ช โฌ ๐ ๐ป ๐ openapi.json
& โคด๏ธ ๐ฅ ๐ช โ ๐ ๐ก ๐ โฎ๏ธ โ ๐ ๐:
import json
from pathlib import Path
file_path = Path("./openapi.json")
openapi_content = json.loads(file_path.read_text())
for path_data in openapi_content["paths"].values():
for operation in path_data.values():
tag = operation["tags"][0]
operation_id = operation["operationId"]
to_remove = f"{tag}-"
new_operation_id = operation_id[len(to_remove) :]
operation["operationId"] = new_operation_id
file_path.write_text(json.dumps(openapi_content))
โฎ๏ธ ๐, ๐ ๏ธ ๐ ๐ ๐ โช๏ธโก๏ธ ๐ ๐ items-get_items
get_items
, ๐ ๐ ๐ฉโ๐ป ๐ ๐ช ๐ ๐
๐ฉโ๐ฌ ๐.
๐ ๐ ๐ฉโ๐ป โฎ๏ธ ๐ ๐¶
๐ ๐ ๐ ๐ openapi.json
, ๐ ๐ ๐ package.json
โ๏ธ ๐ ๐ง๐ฟ ๐, ๐ผ:
{
"name": "frontend-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"generate-client": "openapi --input ./openapi.json --output ./src/client --client axios"
},
"author": "",
"license": "",
"devDependencies": {
"openapi-typescript-codegen": "^0.20.1",
"typescript": "^4.6.2"
}
}
โฎ๏ธ ๐ญ ๐ ๐ฉโ๐ป, ๐ ๐ ๐ โ๏ธ ๐งน ๐ฉโ๐ฌ ๐, โฎ๏ธ ๐ โ, โธ โ, โ๏ธ:
๐ฐ¶
๐โ โ๏ธ ๐ ๐ ๐ฉโ๐ป ๐ ๐ โ :
- ๐ฉโ๐ฌ.
- ๐จ ๐ ๐ช, ๐ข ๐ข, โ๏ธ.
- ๐จ ๐.
๐ ๐ โ๏ธ โธ โ ๐.
& ๐โ ๐ โน ๐ฉโ๐ป ๐, & โป ๐ธ, โซ๏ธ ๐ โ๏ธ ๐ ๐ โก ๐ ๏ธ ๐ช ๐ฉโ๐ฌ, ๐ ๐ โ, & ๐ ๐ ๐ ๐ ๐จ ๐ ๐ ๐. ๐ถ
๐ โ ๐ ๐ฅ ๐ณ ๐ โซ๏ธ ๐ ๐จ ๐ ๐ฉโ๐ป ๐ ๐. & ๐ฅ ๐ ๐ ๐ฉโ๐ป โซ๏ธ ๐ โ ๐ ๐ฅ ๐ โ๏ธ ๐ ๐ ๐ โ๏ธ.
, ๐ ๐ ๐ ๐ โ ๐ถ โช ๐ ๏ธ ๐ต โฉ๏ธ โ๏ธ โ โ ๐ฆ ๐ ๐ ๐ ๐ฉโ๐ป ๐ญ & โคด๏ธ ๐ โน ๐โ โ . ๐ถ