]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
✨ Add support for `read_with_orm_mode`, to support SQLModel relationship attributes...
authorSebastián Ramírez <tiangolo@gmail.com>
Tue, 24 Aug 2021 10:21:05 +0000 (12:21 +0200)
committerGitHub <noreply@github.com>
Tue, 24 Aug 2021 10:21:05 +0000 (10:21 +0000)
fastapi/routing.py
tests/test_read_with_orm_mode.py [new file with mode: 0644]

index 0ad082341f16dddcbdbe8648540578df818e9e7f..63ad7296409f03621d01671738b52d97eb5de569 100644 (file)
@@ -65,6 +65,13 @@ def _prepare_response_content(
     exclude_none: bool = False,
 ) -> Any:
     if isinstance(res, BaseModel):
+        read_with_orm_mode = getattr(res.__config__, "read_with_orm_mode", None)
+        if read_with_orm_mode:
+            # Let from_orm extract the data from this model instead of converting
+            # it now to a dict.
+            # Otherwise there's no way to extract lazy data that requires attribute
+            # access instead of dict iteration, e.g. lazy relationships.
+            return res
         return res.dict(
             by_alias=True,
             exclude_unset=exclude_unset,
diff --git a/tests/test_read_with_orm_mode.py b/tests/test_read_with_orm_mode.py
new file mode 100644 (file)
index 0000000..360ad25
--- /dev/null
@@ -0,0 +1,53 @@
+from typing import Any
+
+from fastapi import FastAPI
+from fastapi.testclient import TestClient
+from pydantic import BaseModel
+
+
+class PersonBase(BaseModel):
+    name: str
+    lastname: str
+
+
+class Person(PersonBase):
+    @property
+    def full_name(self) -> str:
+        return f"{self.name} {self.lastname}"
+
+    class Config:
+        orm_mode = True
+        read_with_orm_mode = True
+
+
+class PersonCreate(PersonBase):
+    pass
+
+
+class PersonRead(PersonBase):
+    full_name: str
+
+    class Config:
+        orm_mode = True
+
+
+app = FastAPI()
+
+
+@app.post("/people/", response_model=PersonRead)
+def create_person(person: PersonCreate) -> Any:
+    db_person = Person.from_orm(person)
+    return db_person
+
+
+client = TestClient(app)
+
+
+def test_read_with_orm_mode() -> None:
+    person_data = {"name": "Dive", "lastname": "Wilson"}
+    response = client.post("/people/", json=person_data)
+    data = response.json()
+    assert response.status_code == 200, response.text
+    assert data["name"] == person_data["name"]
+    assert data["lastname"] == person_data["lastname"]
+    assert data["full_name"] == person_data["name"] + " " + person_data["lastname"]