I have read the documentation of Tortoise-ORM, but, at least to me, the documentation isn't clear about the keyword related_name
in tortoise.field.ForeignKeyField
. It states only:
related_name:
The attribute name on the related model to reverse resolve the foreign key.
I'm using Aerich (the Tortoise-ORM migration manager), and I cannot see a single reference to the related_name
's used in my model. I also checked the database Postgres
and could not find any reference about it. Maybe I don't know where to look.
Unfortunately there is no simple practical examples in Tortoise-ORM documentation about this.
I have a very simple model, something like:
import tortoise
class Toy(tortoise.models.Model):
id = tortoise.fields.IntField(pk=True)
name = tortoise.fields.CharField(max_length=32)
owner = tortoise.fields.ForeignKeyField("models.Person", related_name='toys_owner')
builder = tortoise.fields.ForeignKeyField("models.Person", related_name='toys_builder')
class Person(tortoise.models.Model):
id = tortoise.fields.IntField(pk=True)
name = tortoise.fields.CharField(max_length=32)
async def main():
await tortoise.Tortoise.init(
db_url='sqlite://:memory:',
modules={'models': ["__main__"]}
)
await tortoise.Tortoise.generate_schemas()
person_a = await Person.create(name="Gepheto")
person_b = await Person.create(name="Fairy")
person_c = await Person.create(name="Nobody")
pinocchio = await Toy.create(name="Pinocchio", builder=person_a, owner=person_b)
print(pinocchio)
await tortoise.Tortoise.close_connections()
if __name__ == '__main__':
tortoise.run_async(main())
How related_name
works in this ?
CodePudding user response:
Since the tortoise is inspired by Django, you can check Django docs to get similar answers. It is used when you want to reach Person's Toys.
person_a.toys_builder.all()
This is why it is called a "reverse resolve" event.
CodePudding user response:
After a few tries...
The related_name
value can be used as a name to be referenced in the Foreign Model to access it in reverse direction.
Let's first show up the forward direction. In the example given, from a Toy model instance (in this case pinocchio
), find his builder
or owner
with:
print(f"This is pinnochio owner {pinnochio.owner.name}")
print(f"This is pinnochio builder {pinnochio.owner.builder}")
The related_name
allow us to do the same in opposite direction, from a owner
or builder
, find his/hers toys and iterate over it. For example:
person_b_owned_toys = await person_b.toys_owner.all()
for toy in person_b_owned_toys:
print(toy.name)
Besides the method all()
, the method filter()
can also be used. Returning a QuerySet
with only the entries that match the filter. For example:
person_b_owned_toys = await person_b.toys_owner.filter(name='Pinocchio')
for toy in person_b_owned_toys:
print(toy.name)
The valid keys
on filter
parameter in the reverse direction, are those from Toys
, not from, Person
.