tortoise / tortoise/tortoise-orm
Resolved reverse reference returning a QuerySet instead the ObjectType
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
Given the model with foreignKey:
Toy --(builder)--> Person
With related name:
Person --(toys_built) --> Toy
Defined with this code:
class Toy(tortoise.models.Model):
id = tortoise.fields.IntField(pk=True)
name = tortoise.fields.CharField(max_length=32)
builder = tortoise.fields.ForeignKeyField("models.Person", related_name='toys_built')
class Person(tortoise.models.Model):
id = tortoise.fields.IntField(pk=True)
name = tortoise.fields.CharField(max_length=32)
When resolving the given path
Person --(toys_built)--> Toy --(builder)--> ???
Returns a QuerySet instead a Person as expected.
To Reproduce
import tortoise
class Toy(tortoise.models.Model):
id = tortoise.fields.IntField(pk=True)
name = tortoise.fields.CharField(max_length=32)
builder = tortoise.fields.ForeignKeyField("models.Person", related_name='toys_built')
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()
gepetto = await Person.create(name="Gepheto")
pinocchio = await Toy.create(name="Pinocchio", builder=gepetto)
gepetto_toys_built = await gepetto.toys_built.all()
for toy in gepetto_toys_built:
print(toy.name)
print(f"EXPECTED PERSON {gepetto}")
print(f"EXPECTED PERSON {pinocchio.builder}")
for toy in gepetto_toys_built:
print(type(toy), toy.name)
print(f"EXPECTED PERSON {toy.builder}")
await tortoise.Tortoise.close_connections()
if __name__ == '__main__':
tortoise.run_async(main())
Expected behavior
Since the object returned is of type class Toy, I would expect to be able to resolve toy.builder, exactly like the instance pinocchio.builder. But for some reason it returns a querySet. As we can see, the last printf returns a QuerySet but I expected a Person, as the output shown below
Pinocchio
EXPECTED PERSON <Person>
EXPECTED PERSON <Person>
<class '__main__.Toy'> Pinocchio
EXPECTED PERSON <tortoise.queryset.QuerySet object at 0x7fab33055d00>
Additional context
Python 3.9.7
Tortoise 0.17.8
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
Run the provided SQLite reproduction with the Toy and Person models, then trace how the reverse relation toys_built and the forward builder relation are resolved. Add a regression test showing that toy.builder returns a Person rather than a QuerySet, and verify the existing relation tests still pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, sqlite
- Domain
- backend, database
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100