Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Document not working well with Fastapi & Pydantic

37 views
Skip to first unread message

Emmanuel Steve

unread,
Jan 8, 2024, 7:08:06 AM1/8/24
to MongoEngine Users
I am trying to integrate Mongoengine ORM with Fastapi but am experiencing an issue when trying to return routes:

demo model:
```python
class ModelName(Document):
    name = StringField(required=True)
    title = StringField(required=True)
```

route integration:
```python
router = APIRouter()

@router.get("")
def some_route():
    return ModelName.objects()
```

what is returned:
```python
{
  "_cls": "ModelName"
}
```

When trying to fix the issue, I realized that pydantic tries serializing the document returned but fails due to the `__dict__` method not returning serialized data properly. I also tried working with `.to_mongo()', but pydantic failed to serialize the ObjectID fields.

I read some posts on stack overflow and the suggested solution was to return `.to_json()` which can be returned as a JSON string, but due to the number of routes making use of this, it would be a hassle to update every single route to return `.to_json`, also the frontend dev would have to then parse all responses from the API back to JSON which is unnecessary

I ended up having to create an abstract document with a fix to the `__dict__` method:
```python
class CustomDocument(Document):
    meta = {"abstract": True}

    @property
    def __dict__(self):
        data = {}  # initialize an empty dictionary to store the converted data

        # iterate over key-value pairs in the to_mongo() result
        for key, value in self.to_mongo().items():
            # check if the value is an ObjectId and convert it to a string if necessary
            value = str(value) if isinstance(value, ObjectId) else value

            # update the dictionary with the key-value pair
            data.update({key: value})

        return data

class ModelName(CustomDocument):
    name = StringField(required=True)
    title = StringField(required=True)
```

returned:
```python
[
    {
        "_id": "659be429314d05a57b5e7dad"
        "name": "some text",
        "title": "some text"
    }
]
```
I'd love to know if there is already a solution for this, or possibly one already being worked on. If there isn't, I'll create a pull request with a possible fix to make things easier.

Thank you.
Reply all
Reply to author
Forward
0 new messages