pythonpython-3.xsqlalchemyfastapi

AttributeError: 'Blog' object has no attribute 'items' - FastAPI


I am trying to update a single record in the database by using the PUT operation in FastAPI. But for some reason, I keep getting this error. All other operations work fine except this one. The error is only raised for the update query.

AttributeError: 'Blog' object has no attribute 'items'

Here is the relevant code.

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

class Blog(BaseModel):
    title: str
    body: str

@app.put('/blog/{id}', status_code=status.HTTP_204_NO_CONTENT, response_class=Response)
def update(id: int, request: schemas.Blog, db: Session = Depends(get_db)):
    blog = db.query(models.Blog).filter(models.Blog.id == id)
    if not blog.first():
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
                            detail=f'Blog with id {id} not found')
    blog.update(request)
    db.commit()

This is the StackTrace:

Traceback (most recent call last):
  File "c:\dev\fast-tuts\env\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 396, in run_asgi        
    result = await app(self.scope, self.receive, self.send)
  File "c:\dev\fast-tuts\env\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__        
    return await self.app(scope, receive, send)
  File "c:\dev\fast-tuts\env\lib\site-packages\fastapi\applications.py", line 199, in __call__
    await super().__call__(scope, receive, send)
  File "c:\dev\fast-tuts\env\lib\site-packages\starlette\applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "c:\dev\fast-tuts\env\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
    raise exc from None
  File "c:\dev\fast-tuts\env\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "c:\dev\fast-tuts\env\lib\site-packages\starlette\exceptions.py", line 82, in __call__
    raise exc from None
  File "c:\dev\fast-tuts\env\lib\site-packages\starlette\exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "c:\dev\fast-tuts\env\lib\site-packages\starlette\routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "c:\dev\fast-tuts\env\lib\site-packages\starlette\routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "c:\dev\fast-tuts\env\lib\site-packages\starlette\routing.py", line 41, in app
    response = await func(request)
  File "c:\dev\fast-tuts\env\lib\site-packages\fastapi\routing.py", line 201, in app
    raw_response = await run_endpoint_function(
  File "c:\dev\fast-tuts\env\lib\site-packages\fastapi\routing.py", line 150, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
  File "c:\dev\fast-tuts\env\lib\site-packages\starlette\concurrency.py", line 34, in run_in_threadpool
    return await loop.run_in_executor(None, func, *args)
  File "C:\Python39\lib\concurrent\futures\thread.py", line 52, in run
    result = self.fn(*self.args, **self.kwargs)
  File ".\blog\main.py", line 66, in update
    blog.update(request)
  File "c:\dev\fast-tuts\env\lib\site-packages\sqlalchemy\orm\query.py", line 3190, in update
    upd = upd.values(values)
  File "<string>", line 2, in values
  File "c:\dev\fast-tuts\env\lib\site-packages\sqlalchemy\sql\base.py", line 96, in _generative
    x = fn(self, *args, **kw)
  File "<string>", line 2, in values
  File "c:\dev\fast-tuts\env\lib\site-packages\sqlalchemy\sql\base.py", line 125, in check
    return fn(self, *args, **kw)
  File "c:\dev\fast-tuts\env\lib\site-packages\sqlalchemy\sql\dml.py", line 701, in values
    for k, v in arg.items()
AttributeError: 'Blog' object has no attribute 'items'

Solution

  • This worked for me... the update function wanted to update each part of the object, and so each part must be mentioned. I'm not certain how Bitfumes managed by calling the request object alone.

    blog.update({'title': request.title, 'body': request.body})
    

    EDITED: Referring the to the request dictionary works too:

    blog.update(request.dict())