I'm developing an API service with AIOHTTP, I try to integrate some async ORM, and the first candidate is Tortoise-ORM.
In a Django project I have lots of linked models with __str__
method like the following:
from tortoise.models import Model
from tortoise import fields
class Department(Model):
id = fields.IntField(pk=True)
title = fields.TextField()
upper = fields.ForeignKeyField('models.Department', related_name='children')
def __str__(self):
if self.upper is not None:
return f'{self.id} Department {self.title} of {self.upper.title}'
else:
return f'{self.id} Department {self.title}, head'
class Employee(Model):
id = fields.IntField(pk=True)
name = fields.TextField()
dep = fields.ForeignKeyField('models.Department', related_name='employees')
def __str__(self):
return f'{self.id}. Employee {self.name} of {self.dep.title}'
So that each object shows it's related models in description. But in Tortoise I get an error:
AttributeError: 'QuerySet' object has no attribute 'title'
I guess it's not possible to await the query in the __str__
method. So, is it possible at all use a field of related model to create object representation using Tortoise-ORM?
Tortoise-ORM
does not automatically retrieve related data for the model object from the database, until one asks it to do that. It just generates QuerySet
object for related data without actually hitting the database.
To actually get data you need to use prefetch_related()
or fetch_related()
before printing of your objects. Documentation says:
General rule about how
prefetch_related()
works is that each level of depth of related models produces 1 additional query, so.prefetch_related('events__participants')
will produce two additional queries to fetch your data.
Like so:
emp_one = await Employee.filter(name="Emp_1").prefetch_related("dep").first()
print(emp_one)
emp_two = await Employee.filter(name="Emp_2").first()
await emp_two.fetch_related("dep")
print(emp_two)