darly213 2023. 3. 29. 10:53
728x90

โ€ป FastAPI Tutorial์„ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ดํ•ดํ•œ๋Œ€๋กœ ์ž‘์„ฑํ•œ ๋‚ด์šฉ์œผ๋กœ, ์‹ค์ œ ๋‚ด์šฉ๊ณผ ๋‹ค๋ฅด๊ฑฐ๋‚˜ ํ‹€๋ฆฐ ๋ถ€๋ถ„์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์‹œ๋ฉด ์ฆ‰์‹œ ๋ฐ˜์˜ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

โ€ป ์ค‘๊ฐ„์— ์ดํ•ดํ•˜์ง€ ๋ชปํ•ด ์˜์–ด๋กœ ์˜ฎ๊ฒจ๋‘” ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ถ”ํ›„ ์ˆ˜์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

https://fastapi.tiangolo.com/ko/tutorial/

 

์ž์Šต์„œ - ์‚ฌ์šฉ์ž ์•ˆ๋‚ด์„œ - ๋„์ž…๋ถ€ - FastAPI

์ž์Šต์„œ - ์‚ฌ์šฉ์ž ์•ˆ๋‚ด์„œ - ๋„์ž…๋ถ€ ์ด ์ž์Šต์„œ๋Š” FastAPI์˜ ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋Šฅ์„ ๋‹จ๊ณ„๋ณ„๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๊ฐ ์„น์…˜์€ ์ด์ „ ์„น์…˜์„ ๊ธฐ๋ฐ˜ํ•ด์„œ ์ ์ง„์ ์œผ๋กœ ๋งŒ๋“ค์–ด ์กŒ์ง€๋งŒ, ์ฃผ์ œ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ

fastapi.tiangolo.com


1. ์ฒซ๊ฑธ์Œ

1. FastAPI import

from fastapi import FastAPI

2. ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

app = FastAPI()

3. ๊ฒฝ๋กœ ๋™์ž‘ ์ƒ์„ฑ

@app.get('/')
  • ๊ฒฝ๋กœ: URL์˜ ๋งˆ์ง€๋ง‰ ๋ถ€๋ถ„ ⇒ https://example.com/item/test ์˜ ๊ฒฝ๋กœ = /item/test
  • ๋™์ž‘: HTTP์˜ Method ์ค‘ ํ•˜๋‚˜
    • POST / GET / PUT / DELETE
      • ๋ฐ์ดํ„ฐ ์ƒ์„ฑ / ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ / ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ / ๋ฐ์ดํ„ฐ ์‚ญ์ œ
    • OPTIONS / HEAD / PATCH / TRACE

4. ๊ฒฝ๋กœ ๋™์ž‘ ํ•จ์ˆ˜ ์ •์˜

async def root(): 
    return {"message": "Hello World"}
  • URL / ์— ๋Œ€ํ•œ ์š”์ฒญ์„ ๋ฐ›์„ ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋„๋ก ์ž‘์„ฑ๋จ.
  • ํŒŒ์ด์ฌ ํ•จ์ˆ˜์™€ ๋™์ผ, list, dict, str, int ๋“ฑ์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

2. ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜

  • ๋งค๊ฐœ๋ณ€์ˆ˜ / ๋ณ€์ˆ˜๋ฅผ ๊ฒฝ๋กœ์— ์„ ์–ธ ๊ฐ€๋Šฅ
    • ์ด๋ ‡๊ฒŒ ํ•˜๊ณ  http://127.0.0.1:8000/items/darling ์™€ ๊ฐ™์ด items ๋’ค์— ์•„๋ฌด ๋‚ด์šฉ์„ ์จ๋„ฃ์œผ๋ฉด
    • {"item_id":"darling"}์™€ ๊ฐ™์ด ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋œ๋‹ค.
  • ํƒ€์ž…์ด ์žˆ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜
@app.get('/items/{item_id}') 
async def read_item(item_id: int): 
	return {"item_id": item_id}
  • ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด int ํ˜•์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์ž๋ฃŒํ˜•๋“ค์„ ๋„ฃ์„ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฐœ์ƒ.
{
	"detail":[
    	{
            "loc":["path","item_id"],
            "msg":"value is not a valid integer",
            "type":"type_error.integer"
        }
    ]
 } 
 INFO: 127.0.0.1:63901 - "GET /items/darling HTTP/1.1" 422 Unprocessable Entity

๊ณ ์ • ๊ฒฝ๋กœ๋ฅผ ๊ฐ€์ง„ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์„ ์–ธ ์ˆœ์„œ

  • python์€ script ๊ธฐ๋ฐ˜ → ์œ„์—์„œ๋ถ€ํ„ฐ ์ •์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ณ ์ • ๊ฒฝ๋กœ๋ฅผ ๊ฐ€๋ณ€ ๊ฒฝ๋กœ๋ณด๋‹ค ๋จผ์ € ์„ ์–ธํ•ด์ค˜์•ผํ•œ๋‹ค.
from fastapi import FastAPI 

app = FastAPI() 

@app.get("/users/me") 
async def read_user_me(): 
	return {"user_id": "the current user"} 
    
@app.get("/users/{user_id}") 
async def read_user(user_id: str): 
	return {"user_id": user_id}
  • /users/me ๋กœ ์ ‘์†ํ•˜๋ฉด {"user_id":"the current user"} ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ถœ๋ ฅ๋˜๊ณ , /user/others ๋กœ ์ ‘์†ํ•˜๋ฉด {"user_id":"others"} ๋กœ ์œ ์ € ์•„์ด๋””๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
@app.get("/users/{user_id}") 
async def read_user(user_id: str): 
	return {"user_id": user_id} @app.get("/users/me") 

@app.get("/users/me")
async def read_user_me(): 
	return {"user_id": "the current user"}
  • /user/me ๋กœ ์ ‘์†ํ–ˆ์„ ๋•Œ ์œ„ ํ•จ์ˆ˜๊ฐ€ ๋จผ์ € ์ •์˜๋˜์–ด์„œ ์•„๋ž˜ ํ•จ์ˆ˜์˜ me๊ฐ€ {user_id} ์•„๋ž˜๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜์–ด {"user_id":"me"} ๋ผ๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋„์ถœ๋œ๋‹ค.

์‚ฌ์ „ ์ •์˜ ๊ฒฝ๋กœ

  • ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์ „๋ถ€ ์˜คํ”ˆ๋˜์–ด์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ผ€์ด์Šค ๋ช‡ ๊ฐœ ์ค‘์— ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ. Enum ์ƒ์† ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•ด์„œ ์‚ฌ์ „์— ํด๋ž˜์Šค๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
from enum import Enum

from fastapi import FastAPI


class ModelName(str, Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"


app = FastAPI()


@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    if model_name is ModelName.alexnet:
        return {"model_name": model_name, "message": "Deep Learning FTW!"}

    if model_name.value == "lenet":
        return {"model_name": model_name, "message": "LeCNN all the images"}

    return {"model_name": model_name, "message": "Have some residuals"}
    • ๊ฒฐ๊ณผ
# https://127.0.0.1:8000/models/alexnet
{"model_name":"alexnet","message":"Deep Learning FTW!"}

# https://127.0.0.1:8000/models/lenet
{"model_name":"lenet","message":"LeCNN all the images"}

๊ฒฝ๋กœ ํฌํ•จํ•˜๋Š” ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜

/files/{file_path} ์˜ ๊ฒฝ๋กœ ๋™์ž‘์—์„œ ํ•„์š”๋กœ ํ•˜๋Š” file path๊ฐ€ /root/dnai/myfile.xtx ์ฒ˜๋Ÿผ ๊ฒฝ๋กœ ์ž์ฒด์ธ ๊ฒฝ์šฐ url์ด /files/root/dnai/myfile.txt ๊ฐ€ ๋œ๋‹ค → Open API์—์„œ ์ง€์›ํ•˜์ง€ ์•Š์Œ

๊ทธ๋Ÿฌ๋‚˜ FastAPI์—์„œ๋Š” ๊ฐ€๋Šฅ~

/files/{file_path:path}
  • ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„ = file_path, :path ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๊ฒฝ๋กœ์™€ ์ผ์น˜ํ•ด์•ผํ•จ์„ ๋ช…์‹œ
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
    return {"file_path": file_path}
http://127.0.0.1:8000/files/C:/Users/dk866/Desktop/bearing_test/README.md
{"file_path":"C:/Users/dk866/Desktop/bearing_test/README.md"}

3. ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜

๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์•„๋‹Œ ํ•จ์ˆ˜ ์ž์ฒด์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ = ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜

from fastapi import FastAPI

app = FastAPI()

item_db = [{'itemname' : "va"}, {'itemname' : "mr"}, {'itemname' : "lk"}, {'itemname' : "ie"}, {'itemname' : "sy"}]

@app.get('/')
async def root():
    return 'Hello World'

@app.get('/items/')
async def read_item(skip: int = 0, limit: int = 10):   # skip, limit๊ฐ€ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜
    return item_db[skip:skip + limit]
  • url ์•ˆ์—์„œ ? ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜ ์˜์—ญ์œผ๋กœ ๋“ค์–ด๊ฐ€๊ณ , & ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ตฌ๋ถ„ํ•จ
    • ex) http://127.0.0.1:3000/items/?skip=0&limit=3
    • ๊ธฐ๋ณธ๊ฐ’์— ๋Œ€ํ•œ ์„ค์ •์€ ์ผ๋ฐ˜ ํŒŒ์ด์ฌ ํ•จ์ˆ˜์™€ ๋™์ผ
  • ์„ ํƒ์  ๋งค๊ฐœ๋ณ€์ˆ˜
    • ๊ธฐ๋ณธ๊ฐ’์„ None์œผ๋กœ ์„ค์ •ํ•œ ๊ฒฝ์šฐ → ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์“ฐ๊ณ  ์•„๋‹ˆ๋ฉด ์•ˆ ์“ฐ๋Š” ๊ฒƒ. if๋ฌธ์œผ๋กœ ์žˆ๋Š” ๊ฒฝ์šฐ์™€ ์•„๋‹Œ ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•ด์ฃผ๋ฉด ๋จ.
from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}
  • Bool ํ˜•์— ๋Œ€ํ•œ ๋ฒ”์šฉ์„ฑ
    • True = 1 = true = on = yes = ๋Œ€๋ฌธ์ž

ํ•„์ˆ˜ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜

๊ฒฝ๋กœ ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ž๋ฃŒํ˜• ์„ ์–ธ + ๊ธฐ๋ณธ๊ฐ’ None์œผ๋กœ ์„ค์ •ํ•ด์ฃผ๋ฉด ํ•„์ˆ˜ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜

@app.get('/items/')
async def read_item(skip: int, limit: int = 10):
    return item_db[skip: skip + limit]
@app.get("/items/{item_id}")
async def read_user_item(
    item_id: str, needy: str, skip: int = 0, limit: Union[int, None] = None
):
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item

์ด ๊ฒฝ์šฐ์—๋Š” needy๋Š” ํ•„์ˆ˜, skip์€ ๊ธฐ๋ณธ๊ฐ’์ด 0์ธ integer, limit๋Š” ์„ ํƒ์  ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋œ๋‹ค.


4. Request Body

Request Body : ํด๋ผ์ด์–ธํŠธ → API๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ

Response body : API → ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ

  • API์—์„œ๋Š” ๋Š˜ Response body๋ฅผ ๋ณด๋‚ด์•ผํ•˜์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ๋Š” ๊ทธ๋Ÿด ํ•„์š” ์—†๋‹ค.
    • ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ณด๋‚ด์ฃผ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ‘์ด๋ ‡๊ฒŒ ํ•ด์ฃผ์„ธ์š”’ ํ•˜๊ณ  ๊ทœ๊ฒฉ์„ ์ฃผ๋Š” ์˜๋ฏธ? ์‰ฝ๊ฒŒ ํด๋ž˜์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๊ฐ–๋‹ค์“ธ ์ˆ˜ ์žˆ๋‹ค.
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Union

class Item(BaseModel):
    name: str
    description: Union[str, None] = None # optional 
    price: float
    tax: Union[float, None] = None # optional

app = FastAPI()

@app.post('/items/')
async def create_item(item: Item):
    return item

→ docs์—์„œ ์‹คํ—˜

# request body
{
  "name": "puppet",
  "description": "pebric doll",
  "price": 22480,
  "tax": 1237
}
# response body
{
  "name": "puppet",
  "description": "pebric doll",
  "price": 22480,
  "tax": 1237
}
# curl
curl -X 'POST' \
  'http://127.0.0.1:2000/items/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "puppet",
  "description": "pebric doll",
  "price": 22480,
  "tax": 1237
}'
  • ์—…๋ฐ์ดํŠธ
@app.post('/items/')
async def create_item(item: Item):
    item_dict = item.dict()
    if item.tax:
        price_with_tax = item.price + item.tax
        item_dict.update({"price_with_tax": price_with_tax})
    return item_dict
# request
{
  "name": "o",
  "description": "s",
  "price": 80,
  "tax": 1
}

# response
{
  "name": "o",
  "description": "s",
  "price": 80,
  "tax": 1,
  "price_with_tax": 81
}
  • request body + ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜
@app.put("items/{item_id}")
async def create_item(item_id: int, item: Item):
	return {"item_id": item_id, **item.dict()
  • request body + ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ + ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜
@app.put("/items/{item_id}")
async def create_item(item_id: int, item: Item, q: Union[str, None] = None):
    result = {"item_id": item_id, **item.dict()}
    if q:
        result.update({"q": q})
    return result

5. ํ€ด๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฌธ์ž์—ด ๊ฒ€์ฆ

⇒ parameter์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

@app.get("/itmes/")
async def read_items(q: Union[str, None] = None):
    result = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        result.update({"q" : q})
    return result

Union[str, None] ์ด๋ผ๊ณ  ์“ฐ๋ฉด q๋Š” str์•„๋‹ˆ๋ฉด None์ด๋ผ๋Š” ๋œป + None์œผ๋กœ ๊ธฐ๋ณธ๊ฐ’ ์กด์žฌ = ํ•„์ˆ˜ ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ FastAPI์—์„œ ์•Œ ์ˆ˜ ์žˆ์Œ

http://127.0.0.1:8000/itmes/?q=hello
{"items":[{"item_id":"Foo"},{"item_id":"Bar"}],"q":"hello"}
  • ์ถ”๊ฐ€ validation
from typing import Union
from typing_extensions import Annotated
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/itmes/")
async def read_items(q: Annotated[Union[str, None], Query(max_length=50)] = None):
    result = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        result.update({"q" : q})
    return result
  • Annotated ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
  • Query ์—์„œ max_length ๋ฅผ ์ง€์ •ํ•จ์œผ๋กœ์จ Query์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฑธ๋Ÿฌ์ฃผ๊ธฐ๋ฅผ ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋‹ค.
    • Query๋ฅผ default value๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Annotated ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ๊ถŒ์žฅ๋œ๋‹ค,
    • Using Annotated is recommended instead of the default value in function parameters, it is better for multiple reasons. ๐Ÿค“You could call that same function in other places without FastAPI, and it would work as expected. If there's a required parameter (without a default value), your editor will let you know with an error, Python will also complain if you run it without passing the required parameter.Because Annotated can have more than one metadata annotation, you could now even use the same function with other tools, like Typer. ๐Ÿš€ํ”ผ
    • When you don't use Annotated and instead use the (old) default value style, if you call that function without FastAPI in other place, you have to remember to pass the arguments to the function for it to work correctly, otherwise the values will be different from what you expect (e.g. QueryInfo or something similar instead of str). And your editor won't complain, and Python won't complain running that function, only when the operations inside error out.
    • The default value of the function parameter is the actual default value, that's more intuitive with Python in general. ๐Ÿ˜Œ

ํ•„์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ง€์ •

q: str
q: Annotated[Union[str, None], Query(min_length=3)]
q: Annotated[str, Query(min_length=3)] = ...
q: Annotated[Union[str, None], Query(min_length=3)] = ... # None ํ—ˆ์šฉ, ํ•„์ˆ˜
q: Annotated[str, Query(min_length=3)] = Required  # pydantic

๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ›๊ธฐ

async def read_items(q: Annotated[Union[List[str], None], Query()] = None):
    query_items = {"q": q}
    return query_items
http://127.0.0.1:8000/items/?q=hello&q=darling
{"q":["hello","darling"]}
  • ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋ฆฌ์ŠคํŠธ ์ฃผ๊ธฐ๋„ ๊ฐ€๋Šฅ
async def read_items(q: Annotated[Union[List[str], None], Query()] = ["hello", "darling"):
	query_items = {"q": q}
	return query_items
http://127.0.0.1:8000/items/
{"q":["hello","darling"]}
  • List ๋Œ€์‹  list ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
http://127.0.0.1:8000/items/
{"q":["hello","darling"]}
  • list ๋‚ด๋ถ€ ์ž๋ฃŒํ˜•์ด ๋ญ”์ง€๋Š” ๊ฒ€์‚ฌํ•˜์ง€ ์•Š์Œ

์ถ”๊ฐ€ metadata

  • title
  • description
  • Alias(๋ณ„๋ช…)
async def read_items(q: Annotated[Union[str, None], Query(alias="item-query")] = None)
  • ์ด๋Ÿฌ๋ฉด url์—์„œ q๊ฐ€ ์•„๋‹ˆ๋ผ item-query๋กœ ์ค˜๋„ ์ฐฐ๋–ก๊ฐ™์ด ์•Œ์•„๋“ฃ๋Š”๋‹ค.

6. ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ˆซ์ž ๊ฒ€์ฆ

⇒ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ Query ์™€ ๊ฐ™์€ ์—ญํ• ์„ Path ๊ฐ€ ํ•ด์ค€๋‹ค.

from typing import Union
from fastapi import FastAPI, Path, Query

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: Union[str, None] = Query(default=None, alias="item-query")
):
    result = {"item_id": item_id}
    if q:
        result.update({"q": q})
    return result
  • ์ˆซ์ž ๋ฒ”์œ„ ๊ฒ€์ฆ
async def read_items(
    item_id: int = Path(title="The ID of the item to get", gt=0, lt=1000),
    q: Union[str, None] = Query(default=None, alias="item-query")
):
    result = {"item_id": item_id}
    if q:
        result.update({"q": q})
    return result
  • gt = greater, lt = less then, ge = greater or equal, le = less than or equal
  • ์‹ค์ˆ˜๋„ ๊ฐ€๋Šฅ
728x90