I am using FastAPI framework and writing some data into PostgreSQL database. The issue I am encountering is that I have a function get_current_user()
that returns user credentials (including email), but I am not sure how to access this data from another function s3_create_upload_files()
.
The reason I want to do this is because I want to write the email address and the filename that I am going to upload to the same line in the database after the file is successfully uploaded.
get_current_user()
async def get_current_user(
request: Request,
db: Session = Depends(get_db),
):
token = request.cookies.get("Authorization")
if token is None:
raise HTTPException(status_code=302, headers={"Location": '/auth/login'})
token = token.split("Bearer ")[-1]
try:
payload = jwt.decode(token, os.getenv('SECRET_KEY'), algorithms=["HS256"])
email: str = payload.get("sub")
if email is None:
raise HTTPException(status_code=302, headers={"Location": '/auth/login'})
except jwt.exceptions.ExpiredSignatureError:
raise HTTPException(status_code=302, headers={"Location": '/auth/login'})
user = db.query(User).filter(User.email == email).first()
if user is None:
raise HTTPException(status_code=302, headers={"Location": '/auth/login'})
print(f'Email is {user.email}')
return user # Ensure 'user' is a User object
s3_create_upload_files()
async def s3_create_upload_files(
file: UploadFile = File(...),
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
....CODE HERE,,,,
# Insert data into the database after successful upload
try:
db = SessionLocal()
file_data = User(filename=sanitized_filename, email=current_user.email)
db.add(file_data)
db.commit()
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail=str(e))
finally:
db.close()
I have tried a few different ways to receive the data in s3_create_upload_files()
but all of them cause an error on the HTML side. Same error has come about again "{"detail":"'Depends' object has no attribute 'email'"}"
The error in the backend says
INFO: 192.168.65.1:62133 - "POST /dashboard HTTP/1.1" 500 Internal Server Error
2
Answers
Dependencies, i.e.
Depends
orAnnotated
parameters, are only injected in routes by FastAPI.If your
s3_create_upload_files()
function is called from your route function, you should declare all dependencies as your route parameters and pass them when you calls3_create_upload_file()
. Here is an example:You could do that using one of the approaches described below.
Option 1 – Return a
list
ordict
of dataReturn a
list
of data from the dependency function, and define a proper parameter in the endpoint to expect these data in the appropriate form.To use a
dict
instead, apply the following changes to the example above:Option 1 – Return a custom Python class object
Another way to approach this issue would be to create a custom Python class, instantiate it with the relevant data in the dependency function, and then return it to the endppoint. For simplicity, one could use Python’s
dataclass
—as shown in this answer— where special methods, such as such as__init__()
and__repr__()
can be automatically added.Option 3 – Use
request.state
to store arbitrary dataA further, and maybe simpler, way to store such arbitrary data would be to use
request.state
, which would allow you to retrieve these data later in the endpoint, using theRequest
object. For more details and examples on this approach (as well as on globaldependencies
andrequest.state
in FastAPI), I would highly suggest having a look at this answer, this answer, as well as this and this.