0

So, I am trying to build a simple TODO app using FastApi and MongoDB. All the routes work fine, except for the POST route. When I try to post a "title" and and "description" using the SwaggerUI, it gives me an error. Surprsingly, if I modify the file and save again (the app reloads), the entry magically pops up in the DB. This is the error:

> INFO:     127.0.0.1:35516 - "POST /api/todo HTTP/1.1" 500 Internal Server Error
> ERROR:    Exception in ASGI application
> Traceback (most recent call last):
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 369, in run_asgi
> result = await app(self.scope, self.receive, self.send)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 59, in __call__
> return await self.app(scope, receive, send)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/fastapi/applications.py", line 199, in __call__
> await super().__call__(scope, receive, send)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/starlette/applications.py", line 112, in __call__
> await self.middleware_stack(scope, receive, send)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/starlette/middleware/errors.py", line 181, in __call__
> raise exc from None
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/starlette/middleware/errors.py", line 159, in __call__
> await self.app(scope, receive, _send)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9_/lib/python3.10/site-packages/starlette/middleware/cors.py", line 86, in __call__
> await self.simple_response(scope, receive, send, request_headers=headers)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/starlette/middleware/cors.py", line 142, in simple_response
> await self.app(scope, receive, send)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/starlette/exceptions.py", line 82, in __call__
> raise exc from None
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/starlette/exceptions.py", line 71, in __call__
> await self.app(scope, receive, sender)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/starlette/routing.py", line 580, in __call__
> await route.handle(scope, receive, send)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/starlette/routing.py", line 241, in handle
> await self.app(scope, receive, send)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/starlette/routing.py", line 52, in app
> response = await func(request)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/fastapi/routing.py", line 209, in app
> response_data = await serialize_response(
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/fastapi/routing.py", line 137, in serialize_response
> return jsonable_encoder(response_content)
> File "/home/eeshaan/.local/share/virtualenvs/backend-plIook9\_/lib/python3.10/site-packages/fastapi/encoders.py", line 141, in jsonable_encoder
> raise ValueError(errors)
> ValueError: \[TypeError("'InsertOneResult' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')\]

Following are the code files: main.py

@app.post("/api/todo", response_model = Todo)
async def post_todo(todo: Todo):
    response = await create_todo(todo.dict())
    if response:
        return response
    else:
        raise HTTPException(400, "Something went wrong. Try again.")

database.py


#mongoDB driver
import asyncio
from motor.motor_asyncio import AsyncIOMotorClient

#setup the connection to the database
client = AsyncIOMotorClient("mongodb://127.0.0.1:27017/")



    

async def create_todo(todo):
    # take the the todo var in a dictionary form of key value pairs, and directly add them to the documents.
    document = todo
  
    result = await collection.insert_one(document)
    return result




model.py

#this file helps us define a model on how our data from the databsse should look like

from pydantic import BaseModel


#specify the model for the todo. A title and a description
class Todo(BaseModel):
    title : str
    description : str
Eeshaan
  • 21
  • 4
  • I suggest your read the article about how to create a [mcve]. You stated yourself that the problem arises with the POST route, so all the other routes are irrelevant to the question. Same goes for those database functions except `create_todo`. Also instead of splitting your code up into multiple files here, your MRE could easily be fit into a single code snippet, if you boil it down to the essentials that cause your error. Leaving out irrelevant code that readers would otherwise first have to dig through shows that you respect their time. – Daniil Fajnberg Jul 21 '23 at 08:05
  • Your `create_todo` method returns the result of the insert operation (`result = await collection.insert_one(document)`) - This is not something that FastAPI knows how to serialize and return to the user. Return the fields you want to return from that result explicitly. – MatsLindh Jul 21 '23 at 08:09
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Jul 21 '23 at 17:39
  • Yes, sorry for the inconvenience. I have reduced the problem into a MRE – Eeshaan Jul 29 '23 at 11:47
  • @MatsLindh can you be a bit more specific? – Eeshaan Jul 30 '23 at 14:57
  • What do you want your endpoint to return to the user? What you're currently returning (the result of the insert operation, which is probably some sort of mongodb result object or similar) - is an object which FastAPI has _no_ idea what to do with - i.e. what you _actually_ want to happen with that object or result. Convert it to something FastAPI knows how to handle - either a dict with native types (str/float/int/etc.) or a pydantic object. – MatsLindh Jul 30 '23 at 18:42

0 Answers0