tortoise / tortoise/tortoise-orm
Missing attributes when using fetch_related
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5.6k
- Forks
- 516
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 9
Description
Describe the bug
Hello,
I am using FastApi+Tortoise to simulate a small Facebook-like demo project. I have users linked to friend requests, where each friend request has a requestor and a requestee.
The user object derived from awaiting Users.filter(...).first(...) correctly shows related obejcts in the friendships_requestee and friendships_requestor attributes:

The derived pydantic model however drops the references to the user objects in the friend requests:

I appreciate that keeping a reference to the current user might be redundant, but it would be helpful to keep a reference to the other user
To Reproduce
Models:
class Users(models.Model):
"""
The User model
"""
id = fields.CharField(pk=True, max_length=100)
#: This is a username
username = fields.CharField(max_length=20, unique=True)
name = fields.CharField(max_length=50, null=True)
email = fields.CharField(max_length=320, null=False)
friends: fields.ManyToManyRelation["Users"] = fields.ManyToManyField(
'models.Users', through='friendships', null=False, default=[]
)
class FriendRequest(models.Model):
requestor = fields.ForeignKeyField('models.Users', null=False, related_name='friendships_requestor')
requestee = fields.ForeignKeyField('models.Users', null=False, related_name='friendships_requestee')
created_at = fields.DatetimeField(auto_now=True)
accepted_at = fields.DatetimeField(null=True)
class Meta:
unique_together=(('requestor', 'requestee'))
Fetching:
user = await Users.filter(id=user_id).first()
await user.fetch_related("friendships_requestee__requestor")
await user.fetch_related("friendships_requestee__requestee")
await user.fetch_related("friendships_requestor__requestor")
await user.fetch_related("friendships_requestor__requestor")
user_pydantic = await UserOut_Pydantic.from_tortoise_orm(user)
Expected behavior
User FKs in FriendRequest objects retrieved with fetch_related to be kept.
Additional context
I was able to 'hack' a solution by manually creating and populating the models:
class FriendRequestOut(BaseModel):
requestor_id: str
requestee_id: str
created_at: datetime
accepted_at: Union[datetime, None]
class TestUserOut(BaseModel):
id: str
username: str
email: str
friendships_requestor: List[FriendRequestOut]
friendships_requestee: List[FriendRequestOut]
test_user_out = TestUserOut(**{
'id': user.id,
'username': user.username,
'email': user.email,
'friendships_requestor': [FriendRequestOut(**{
'created_at': related_object.created_at,
'accepted_at': related_object.accepted_at,
'requestor_id': related_object.requestor_id,
'requestee_id': related_object.requestee_id
}) for related_object in user.friendships_requestor.related_objects],
'friendships_requestee': [FriendRequestOut(**{
'created_at': related_object.created_at,
'accepted_at': related_object.accepted_at,
'requestor_id': related_object.requestor_id,
'requestee_id': related_object.requestee_id
}) for related_object in user.friendships_requestee.related_objects]
})
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the fetch_related calls and UserOut_Pydantic.from_tortoise_orm shown in the reproduction, then trace how the loaded FriendRequest relations are converted into Pydantic models. Reproduce the example and verify that the expected user foreign-key references are retained in the serialized FriendRequest objects.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fastapi, python
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100