Skip to content

Commit 2454f8e

Browse files
committed
fix backlink serialization when link data is fetched
1 parent ea651ad commit 2454f8e

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

beanie/odm/fields.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,12 @@ def __modify_schema__(cls, field_schema: Dict[str, Any]):
516516
}
517517
)
518518

519+
@staticmethod
520+
def serialize(value: Union[Link[T], BaseModel]):
521+
if isinstance(value, Link):
522+
return value.to_dict()
523+
return value.dict()
524+
519525
def to_ref(self):
520526
return self.ref
521527

@@ -524,7 +530,7 @@ def to_dict(self):
524530

525531

526532
if not IS_PYDANTIC_V2:
527-
ENCODERS_BY_TYPE[Link] = lambda o: o.to_dict()
533+
ENCODERS_BY_TYPE[Link] = lambda o: o.serialize()
528534

529535

530536
class BackLink(Generic[T]):
@@ -535,6 +541,12 @@ def __init__(self, document_class: Type[T]):
535541

536542
if IS_PYDANTIC_V2:
537543

544+
@staticmethod
545+
def serialize(value: Union[BackLink[T], BaseModel]):
546+
if isinstance(value, BackLink):
547+
return value.to_dict()
548+
return value.model_dump(mode="json")
549+
538550
@classmethod
539551
def wrapped_validate(
540552
cls, source_type: Type[Any], handler: GetCoreSchemaHandler
@@ -565,7 +577,7 @@ def __get_pydantic_core_schema__(
565577
values_schema=core_schema.any_schema(),
566578
),
567579
serialization=core_schema.plain_serializer_function_ser_schema(
568-
lambda instance: cls.to_dict(instance),
580+
lambda instance: cls.serialize(instance),
569581
return_schema=core_schema.dict_schema(),
570582
when_used="json-unless-none",
571583
),
@@ -610,13 +622,19 @@ def __modify_schema__(cls, field_schema: Dict[str, Any]):
610622
}
611623
)
612624

625+
@staticmethod
626+
def serialize(value: Union[BackLink[T], BaseModel]):
627+
if isinstance(value, BackLink):
628+
return value.to_dict()
629+
return value.dict()
630+
613631
def to_dict(self) -> dict[str, str]:
614632
document_class = DocsRegistry.evaluate_fr(self.document_class) # type: ignore
615633
return {"collection": document_class.get_collection_name()}
616634

617635

618636
if not IS_PYDANTIC_V2:
619-
ENCODERS_BY_TYPE[BackLink] = lambda o: o.to_dict()
637+
ENCODERS_BY_TYPE[BackLink] = lambda o: o.serialize()
620638

621639

622640
class IndexModelField:

tests/fastapi/routes.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,8 @@ async def create_house_new(house: House = Body(...)):
7171
await house.save(link_rule=WriteRules.WRITE)
7272
await house.sync()
7373
return house
74+
75+
76+
@house_router.get("/person/{id}", response_model=Person)
77+
async def get_person(id: PydanticObjectId):
78+
return await Person.get(id, fetch_links=True, nesting_depth=1)

tests/fastapi/test_api.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,22 @@ async def test_create_house_new(api_client):
6666
assert resp_json["name"] == payload["name"]
6767
assert resp_json["owner"]["name"] == payload["owner"]["name"][-3:]
6868
assert resp_json["owner"]["house"]["collection"] == "House"
69+
70+
71+
async def test_get_person(api_client):
72+
payload = {
73+
"name": "FreshHouse",
74+
"owner": {"name": "will_be_overridden_to_Bob"},
75+
}
76+
resp = await api_client.post("/v1/house", json=payload)
77+
resp_json = resp.json()
78+
79+
person_id = resp_json["owner"].get("id")
80+
if person_id is None:
81+
person_id = resp_json["owner"].get("_id")
82+
assert person_id is not None
83+
84+
resp2 = await api_client.get(f"/v1/person/{person_id}")
85+
86+
resp2_json = resp2.json()
87+
assert resp2_json["name"] == payload["owner"]["name"][-3:]

0 commit comments

Comments
 (0)