jyablonski
jyablonski

Reputation: 939

FastAPI Depends w/ get_db failing for PUT endpoint

I'm working on a FastAPI Project w/ some basic user endpoints. I recently shifted my project around to use routers to separate all of the endpoints out into individual files, but this has caused my only PUT endpoint to start failing while all of the GET ones still function just fine.

When I hit the POST endpoint to create the user, it works fine and the user gets created. When I hit the PUT endpoint to update that same user, I immediately get an error about AttributeError: 'UserBase' object has no attribute 'query'.

It's failing while trying to run the existing_user_record line. I put a print(type(db)) line in each endpoint and for some reason the PUT endpoint is returning 2 objects for the db type, while in the POST endpoint it correctly only returns 1 object (the db session). I believe this is causing my issue in the PUT endpoint, but I don't know why it's happening or how to fix it. Why would it return src.schemas.UserBase here?

![enter image description here

Below is some of my code and file structure.

# src/schemas.py

class UserBase(BaseModel):
    username: str
    password: str
    email: Optional[str]
    created_at: datetime = datetime.now(timezone.utc)

    class Config:
        orm_mode = True


class UserCreate(UserBase):
    pass

# src/database.py
SQLAlchemyInstrumentor().instrument(engine=engine)

# separate database sessions for different users essentially.
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, future=True)

Base = declarative_base()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()
# src/routers/users.py

from src.database import get_db
from src.models import Users
from src.schemas import UserBase, UserCreate

router = APIRouter()

@router.post("/users", response_model=UserCreate, status_code=201)
async def create_users(create_user_request: UserCreate, db: Session = Depends(get_db)):
    print(type(db))
    record_check = (
        db.query(Users).filter(Users.username == create_user_request.username).first()
    )

    if record_check:
        raise HTTPException(
            status_code=403,
            detail="Username already exists!  Please select another username.",
        )

    return create_user(db, create_user_request)


@router.put("/users/{username}", response_model=UserBase)
def update_user(
    update_user_request: UserBase, username: str, db: Session = Depends(get_db)
):
    print(type(db))

    # it fails here because of db.query() even though db.query works fine in the POST endpoint?
    existing_user_record = db.query(Users).filter(Users.username == username).first()

    if not existing_user_record:
        raise HTTPException(
            status_code=400,
            detail="That old Username doesn't exist!  Please select another username.",
        )

    new_record_check = (
        db.query(Users).filter(Users.username == update_user_request.username).first()
    )

    if new_record_check:
        raise HTTPException(
            status_code=403,
            detail="The new requested Username already exists!  Please select another username.",
        )

    return update_user(db, existing_user_record, update_user_request)
# the requests i'm makiing
import requests
api = "http://127.0.0.1:8000"

# this works fine
df = requests.post(f"{api}/users", json = {"username": "jyablonski", "password": "helloworld", "email": "[email protected]"})

# this fails because of that - AttributeError: 'UserBase' object has no attribute 'query'`enter code here`
df = requests.put(f"{api}/users/jyablonski", json = {"username": "jyablonski_new_name", "password": "helloworld", "email": "[email protected]"})

I feel like I've tried a lot of things but haven't gotten anywhere, any help would be appreciated!

Upvotes: 1

Views: 241

Answers (1)

jyablonski
jyablonski

Reputation: 939

python_user found the solution! there was some recursion weirdness occurring because my router endpoint name had the same name as the SQL function from src/crud.py that I return in the endpoint which actually updates the user record. Once I fixed the endpoint name so it wasn't the same as that crud function the endpoint functionality was restored.

Upvotes: 1

Related Questions