FastAPI Depends 使用 get_db 在 PUT 端点失败。

huangapple go评论81阅读模式
英文:

FastAPI Depends w/ get_db failing for PUT endpoint

问题

我正在开发一个FastAPI项目,其中包含一些基本的用户端点。最近,我将项目重构,使用路由器将所有端点分离到单独的文件中,但这导致我的唯一的PUT端点开始失败,而所有的GET端点仍然正常工作。

当我访问POST端点以创建用户时,它可以正常工作,并且用户会被创建。但是,当我访问PUT端点以更新同一用户时,我立即收到关于“AttributeError: 'UserBase'对象没有属性'query'”的错误消息。

问题出现在尝试运行“existing_user_record”行时。我在每个端点中都加入了一行“print(type(db))”,但出于某种原因,PUT端点返回了2个db类型的对象,而在POST端点中,它正确地只返回1个对象(db会话)。我认为这是导致PUT端点问题的原因,但我不知道为什么会发生这种情况,也不知道如何修复它。为什么会在这里返回'src.schemas.UserBase'?

以下是我的一些代码和文件结构。

# 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)

# 为不同用户分别创建数据库会话。
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))

    # 问题出现在这里,因为db.query(),即使在POST端点中db.query也能正常工作?
    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)
# 我正在发送的请求
import requests
api = "http://127.0.0.1:8000"

# 这个工作正常
df = requests.post(f"{api}/users", json={"username": "jyablonski", "password": "helloworld", "email": "nobody@gmail.com"})

# 这个失败了,因为出现了“AttributeError: 'UserBase'对象没有属性'query'”的错误消息。
df = requests.put(f"{api}/users/jyablonski", json={"username": "jyablonski_new_name", "password": "helloworld", "email": "nobody@gmail.com"})

我觉得我已经尝试了很多方法,但还没有取得任何进展,任何帮助都将不胜感激!

英文:

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?

FastAPI Depends 使用 get_db 在 PUT 端点失败。

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": "nobody@gmail.com"})

# 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": "nobody@gmail.com"})

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

答案1

得分: 1

python_user找到了解决办法!出现了一些递归奇怪的问题,因为我的路由器端点名称与我在端点中返回的src/crud.py中的SQL函数具有相同的名称,该函数实际上会更新用户记录。一旦我修复了端点名称,使其不与crud函数相同,端点功能就恢复了。

英文:

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.

huangapple
  • 本文由 发表于 2023年5月29日 22:56:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76358355.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定