개발하자

Fast API 변수 쿼리 매개 변수

Cuire 2023. 4. 18. 17:57
반응형

Fast API 변수 쿼리 매개 변수

나는 요청을 수락하고 사용자가 승인되었는지 확인한 후 성공하면 다른 URL로 리디렉션하는 Fast API 서버를 작성하고 있다.

URL 매개 변수를 넘겨야 합니다. 예를 들어, 로 리디렉션하여 이전에 할당된 매개 변수를 유지해야 합니다.

매개 변수는 내가 제어하지 않으며 언제든지 변경될 수 있습니다.

어떻게 하면 이것을 달성할 수 있을까요?

코드:

from fastapi import FastAPI
from starlette.responses import RedirectResponse

app = FastAPI()

@app.get("/data/")
async def api_data():
    params = '' # I need this value
    url = f'http://some.other.api/{params}'
    response = RedirectResponse(url=url)
    return response




그들이 이야기하는 문서에서, 그리고 나서 나는 다음과 같은 것으로 이끈다:

from fastapi import FastAPI, Request
from starlette.responses import RedirectResponse

app = FastAPI()

@app.get("/data/")
async def api_data(request: Request):
    params = request.query_params
    url = f'http://some.other.api/?{params}'
    response = RedirectResponse(url=url)
    return response



FastAPI 문서에 언급된 바와 같이.

 @app.get("/")
 def read_root(param1: Optional[str] = None, param2: Optional[str] = None):
     url = f'http://some.other.api/{param1}/{param2}'
     return {'url': str(url)}

산출량

enter image description here

enter image description here




API를 시작할 때 쿼리 매개 변수를 알고 있지만 동적으로 설정하려면 다음을 수행합니다:

from fastapi import FastAPI, Depends
from pydantic import create_model

app = FastAPI()

# Put your query arguments in this dict
query_params = {"name": (str, "me")}

query_model = create_model("Query", **query_params) # This is subclass of pydantic BaseModel

# Create a route
@app.get("/items")
async def get_items(params: query_model = Depends()):
    params_as_dict = params.dict()
    ...

이 기능은 자동 설명서에서 파라미터를 확인할 수 있다는 이점이 있습니다:

Swagger UI

그러나 API를 시작할 때 동적으로 정의할 수 있습니다.

모델에 딕트, 목록 또는 기타 기본 모델이 필드 유형으로 있는 경우 요청 본문이 팝업됩니다. GET에는 본문 내용이 없어야 하므로 이러한 유형은 피해야 합니다.

동적 모델 작성에 대한 자세한 내용은 에서 참조하십시오.




저는 , 그리고 객체 자체의 조합을 사용합니다.

다음과 같은 HTTP 요청의 예가 있습니다

# imports
from typing import Union
from pydantic import BaseModel
from fastapi import Depends, Request

# the base model
class QueryParams(BaseModel):
    required: str
    optional: Union[None, str] = None
    dynamic: dict

# dependency
async def query_params(
    request: Request, requiredParam1: str, optionalParam1: Union[None, str] = None
    ):
    # process the request here
    dynamicParams = {}
    for k in request.query_params.keys():
        if 'dynamicParam' not in k:
            continue
        dynamicParams[k] = request.query_params[k]

    # also maybe do some other things on the arguments
    # ...

    return {
        'required': requiredParam1,
        'optional': optionalParam1,
        'dynamic': dynamicParams
    }

# the endpoint
@app.get("api/")
async def hello(params: QueryParams = Depends(query_params)):

    # Maybe do domething with params here,
    # Use it as you would any BaseModel object
    # ...

    return params

요청 개체를 사용하는 방법은 Starlette 문서를 참조하십시오:

다른 모듈을 삽입할 수 있으며 개체를 명시적으로 전달하기 위해 코드를 추가할 필요가 없습니다. FastAPI는 사용자가 엔드포인트에 전화를 걸 때 이미 그렇게 합니다 :)




이것은 제가 @Hajar Razip에서 더 비슷한 접근법을 사용하여 파생한 코드입니다:

from pydantic import (
    BaseModel,
)
from typing import (
    Dict,
    List,
    Optional,
)

from fastapi import (
    Depends,
    FastAPI,
    Query,
    Request,
)


class QueryParameters(BaseModel):
    """Model for query parameter."""
    fixId: Optional[str]
    fixStr: Optional[str]
    fixList: Optional[List[str]]
    fixBool: Optional[bool]
    dynFields: Dict

    _aliases: Dict[str,str] = {"id": "fixId"}

    @classmethod
    def parser(
        cls, 
        request: Request,
        fixId: Optional[str] = Query(None, alias="id"),
        fixStr: Optional[str] = Query(None),
        fixList: Optional[List[str]] = Query(None),
        fixBool: bool = Query(True),
    ) -> Dict:
        """Parse query string parameters."""
        dynFields = {}
        reserved_keys = cls.__fields__
        query_keys = request.query_params
        for key in query_keys:
            key = cls._aliases.get(key, key) 
            if key in reserved_keys:
                continue
            dynFields[key] = request.query_params[key]
        
        return {
            "fixId": fixId,
            "fixStr": fixStr,
            "fixList": fixList,
            "fixBool": fixBool,
            "dynFields": dynFields
        }


app = FastAPI()


@app.get("/msg")
def get_msg(
    parameters: QueryParameters = Depends(
            QueryParameters.parser,
    ),
) -> None:
    return parameters

출력 문서는 다음과 같습니다

enter image description here

여기서 GET /msg를 호출한 결과입니다

> curl -s -X 'GET' 'http://127.0.0.1:8000/msg?id=Victor&fixStr=hi&fixList=eggs&fixList=milk&fixList=oranges&fixBool=true' -H 'accept: application/json' | python3 -m json.tool
{
    "fixId": "Victor",
    "fixStr": "hi",
    "fixList": [
        "eggs",
        "milk",
        "oranges"
    ],
    "fixBool": true,
    "dynFields": {}
}

동적 필드를 사용하는 GET /msg 호출입니다

>  curl -s -X 'GET' 'http://127.0.0.1:8000/msg?id=Victor&fixStr=hi&fixList=eggs&fixList=milk&fixList=oranges&fixBool=true&key1=value1&key2=value2' -H 'accept: application/json' | python3 -m json.tool
{
    "fixId": "Victor",
    "fixStr": "hi",
    "fixList": [
        "eggs",
        "milk",
        "oranges"
    ],
    "fixBool": true,
    "dynFields": {
        "key1": "value1",
        "key2": "value2"
    }
}



임의 개수의 조회 매개 변수에 대해 두 개의 매개 변수를 모두 사용할 수 있습니다. 이 두 개의 매개 변수에는 두 개의 매개 변수 이름과 값이 모두 포함됩니다. 사전으로 fastapi 요청 개체에서 매개 변수를 검색하고 사전의 값을 목록으로 분할합니다. 그런 다음 목록에서 매개 변수 이름의 인덱스를 사용하여 목록의 값에 액세스합니다.

URL은 다음과 같을 수 있습니다.

params = request.query_params._dict
# {'names': 'names2,names1,names3', 'values': 'value1,value2,value3'}
print(params)

for key, value in params.items():
  value = value.split(',')
  params[key] = value

# {'names': ['names2', 'names1', 'names3'], 'values': ['value1', 'value2', 'value3']}
print(params)


index = params['names'].index('names2')
value = params['values'][index]
# 'value3'
print(value)

반응형