My script looks like this
from pydantic import BaseModel
from fastapi import FastAPI
class Credentials(BaseModel):
url:str
username:str
password:str
#app.post("/"/credentials"")
async def post_credentials(conn: Required):
return conn
#app.get("/main")
async def receive_from_post():
I would like to know if there is a way to retrieve the data from "POST" in "GET"
I am testing loginradius for authentication in a fastapi app but cant seem to get the redirect or modal form to work correctly. I have tried using the OAuth2PasswordBearer and OAuth2AuthorizationCodeBearer classes but neither worked as desired. I would like to be able to click the "Authorize" button and either get redirected to the loginradius login page https://<app_name>.hub.loginradius.com (and returned to the api page with the token from loginradius) or render the loginradius login/registration form instead of the fastapi OAuth2PasswordBearer form. example:
Instead of
Desired outcome
Small Code Snippet
"""Fastapi routes for all User related endpoints"""
from fastapi import APIRouter, Depends
from fastapi.security import OAuth2PasswordBearer
router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
# oauth2_scheme = OAuth2AuthorizationCodeBearer(
# tokenUrl="https://<app_name>.hub.loginradius.com",
# authorizationUrl="https://<app_name>.hub.loginradius.com")
#router.post("/me", response_model=None)
def create_me(token: str = Depends(oauth2_scheme)):
return {"token": token}
Is that possible?
Thanks
I'm trying to move my rest api project from flask to FastAPI
on my get function I made it very easy to get all the filters and by using flask I used the command
filter_value = request.args.get(f'filter[{filter_name}]')
where filter_name changed between all the fields i have on my object and that's how i could read urls like
http://127.0.0.1:8000/beers?filter[isbn]=72533
but now when I moved to fast api I can't find a way to read url like this.
Naming parameters in such a way, in my opinion, is not good.
Despite that, here's a working example.
from fastapi import FastAPI, Request
app = FastAPI()
#app.get("/")
async def get(req: Request):
if "filter[filter]" in req.query_params:
return req.query_params["filter[filter]"]
return ""
You have to directly access the request and manipulate it, since it is not possible to declare it as a function's parameter due to it's name. Choosing a different naming convention would allow to define the parameter as in the example below
from fastapi import FastAPI, Request
app = FastAPI()
#app.get("/")
async def get(my_parameter=None):
if my_parameter is not None:
return my_parameter
return ""
I try to migrate from Flask to FastAPI, and I was wondering if there is something similar to Flask's:
payload = request.form.to_dict(flat=False)
payload = {key:payload[key][0] for key in payload}
for FastAPI.
Until now I've found only some hacks, were you still had to implement one-by-one all the form's arguments to a function:
from pydantic import BaseModel
class FormData(BaseModel):
alfa: str=Form(...)
vita: str=Form(...)
async def Home(request: Request, form_data:FormData)
This example is of course better in readability than the standard form handling:
async def Home(username: str = Form(...), something_else: str = Form(...)):
But still it's quite restricting, due to the necessary declaration of all form fields.
Is there any other more agnostic & elegant approach?
Thanks in advance & I apologize if this a trivial question I've failed to find through googling :)
You can get the underlying starlette request and use its request.form() method. It requires python-multipart to work:
from fastapi import FastAPI, Request
app = FastAPI()
#app.post("/example")
async def example(request: Request):
form_data = await request.form()
return form_data
Example of calling it:
C:\>curl -X POST "http://localhost:8000/example" -d "hello=there&another=value"
{"hello":"there","another":"value"}
FastAPI automatically generates a schema in the OpenAPI spec for UploadFile parameters.
For example, this code:
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
#app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(..., description="The file")):
return {"filename": file.filename}
will generate this schema under components:schemas in the OpenAPI spec:
{
"Body_create_upload_file_uploadfile__post": {
"title": "Body_create_upload_file_uploadfile__post",
"required":["file"],
"type":"object",
"properties":{
"file": {"title": "File", "type": "string", "description": "The file","format":"binary"}
}
}
}
How can I explicitly specify the schema for UploadFiles (or at least its name)?
I have read FastAPIs docs and searched the issue tracker but found nothing.
I answered this over on FastAPI#1442, but just in case someone else stumbles upon this question here is a copy-and-paste from the post linked above:
After some investigation this is possible, but it requires some monkey patching. Using the example given here, the solution looks like so:
from fastapi import FastAPI, File, UploadFile
from typing import Callable
app = FastAPI()
#app.post("/files/")
async def create_file(file: bytes = File(...)):
return {"file_size": len(file)}
#app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
return {"filename": file.filename}
def update_schema_name(app: FastAPI, function: Callable, name: str) -> None:
"""
Updates the Pydantic schema name for a FastAPI function that takes
in a fastapi.UploadFile = File(...) or bytes = File(...).
This is a known issue that was reported on FastAPI#1442 in which
the schema for file upload routes were auto-generated with no
customization options. This renames the auto-generated schema to
something more useful and clear.
Args:
app: The FastAPI application to modify.
function: The function object to modify.
name: The new name of the schema.
"""
for route in app.routes:
if route.endpoint is function:
route.body_field.type_.__name__ = name
break
update_schema_name(app, create_file, "CreateFileSchema")
update_schema_name(app, create_upload_file, "CreateUploadSchema")
You can edit the OpenAPI schema itself. I prefer to just move these schemas to the path (since they are unique to each path anyway):
from fastapi import FastAPI, File, UploadFile
from fastapi.openapi.utils import get_openapi
app = FastAPI()
#app.post("/uploadfile/")
async def create_upload_file(file1: UploadFile = File(...), file2: UploadFile = File(...)):
pass
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="Custom title",
version="2.5.0",
description="This is a very custom OpenAPI schema",
routes=app.routes,
)
# Move autogenerated Body_ schemas, see https://github.com/tiangolo/fastapi/issues/1442
for path in openapi_schema["paths"].values():
for method_data in path.values():
if "requestBody" in method_data:
for content_type, content in method_data["requestBody"]["content"].items():
if content_type == "multipart/form-data":
schema_name = content["schema"]["$ref"].lstrip("#/components/schemas/")
schema_data = openapi_schema["components"]["schemas"].pop(schema_name)
content["schema"] = schema_data
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi