I am so sorry if this is a duplicate question but I barely see it anywhere except this one website. This website originally helps people to make queries in Google Sheet through REST API. Their links go like this example:
spreadsheetID/sheetName?filter[ColumnName]=aiman
I just wonder how to do it in FastAPI especially for params filter[columnName]. The columnName is also a variable which according name of column. I've already read this but cannot figure out it well. Any language also I appreciate.
CodePudding user response:
There is nothing built into the FastAPI to achieve that, but we can write it! We need function that parse parameter:
import re
def parse_param(param, value):
regex = r"(?P<op>.*)\[(?P<col>.*)\]"
if m := re.search(r, param):
return {"op": m.group("op"), "col": m.group("col"), "val": value}
return {param: value}
Now it's time to use it, the simplest way would be use underlying Starlete request and parse url
from fastapi import Request
@app.get("/sheetName")
def endpoint(r: Request):
k, v = next(iter(r.query_params.items())) # Assuming there is only one parameter
print(parse_param(k, v))
If you would like to some FastAPI magic, you have another two options
@app.middleware("http")
async def preprocess(request: Request, call_next):
k, v = next(iter(request.query_params.items()))
request._query_params = QueryParams(parse_param(k, v))
request.scope["query_string"] = str(request._query_params).encode("ascii")
response = await call_next(request)
return response
from fastapi.routing import APIRoute
from starlette.datastructures import QueryParams
class BracketRequest(Request):
@property
def query_params(self):
k, v = next(iter(super().query_params.items()))
return QueryParams(parse_param(k, v))
class BracketRoute(APIRoute):
def get_route_handler(self):
original_route_handler = super().get_route_handler()
async def custom_route_handler(request: Request):
request = BracketRequest(request.scope, request.receive)
return await original_route_handler(request)
return custom_route_handler
app.router.route_class = BracketRoute
Second solution allows you to assign such logic only for specific routers. In both cases you can use your endpoint with help of FastAPI validation now:
@app.get("/sheetName")
def endpoint(op: str, col: str, val: Any):
print(op, col, val)
This approach has limitations (like what if there can be more parameters? Or more parameters with brackets?) and exact solutions depends on specific needs, but they should give you enough insight how to solve them.