Home > Net >  Usage of keyword `related_name` in `tortoise.field.ForeignKeyField`
Usage of keyword `related_name` in `tortoise.field.ForeignKeyField`

Time:10-31

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.

  • Related