Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
e402597
chore(deps): remove darglint
waketzheng Oct 25, 2025
f45195d
chore: upgrade deps
waketzheng Oct 30, 2025
0a85b6a
feat: foreignkey to model type
waketzheng Oct 30, 2025
627923e
refactor: rollback unnecessary changes
waketzheng Nov 28, 2025
aa2ecc6
refactor: only imports AbstractEventLoop when type checking
waketzheng Nov 28, 2025
94e2c18
refactor: use from thread instead of anyio.run
waketzheng Nov 28, 2025
e8d725c
refactor: only imports AbstractEventLoop when type checking
waketzheng Nov 28, 2025
6f5910f
Merge branch 'refactor-run-async' into ci-py3.14
waketzheng Nov 28, 2025
5d49525
fix union annotation error
waketzheng Nov 28, 2025
3cb83bc
Add py3.14 to ci
waketzheng Nov 28, 2025
d6e9ef2
chore: upgrade deps
waketzheng Nov 30, 2025
c7958f4
tests: use xy instead ab
waketzheng Nov 30, 2025
963d99b
chore: upgrade deps
waketzheng Nov 30, 2025
68b678c
Merge remote-tracking branch 'upstream/develop' into feat-foreignkey-…
waketzheng Nov 30, 2025
cee4d7c
chore: upgrade deps
waketzheng Dec 1, 2025
2a63982
refactor: rename position argument for foreignkey field `model_name` …
waketzheng Dec 1, 2025
abe8a06
tests: check recursive example output
waketzheng Dec 1, 2025
99ad304
Merge branch 'ci-py3.14' into feat-foreignkey-to-model
waketzheng Dec 1, 2025
6b1317c
chore: upgrade deps
waketzheng Dec 7, 2025
cef1bc7
Merge remote-tracking branch 'upstream/develop' into feat-foreignkey-…
waketzheng Dec 10, 2025
b135fd3
chore: upgrade deps
waketzheng Dec 10, 2025
93d5fc0
refactor: use try-except instead of hasattr
waketzheng Dec 10, 2025
5a6850a
Remove 'self' for recursive support
waketzheng Dec 10, 2025
6a66445
fix: m2m describe json dumps error
waketzheng Dec 10, 2025
44a0169
Merge branch 'develop' of github.com:tortoise/tortoise-orm into feat-…
waketzheng Dec 12, 2025
aabdbfc
chore: upgrade deps, update changelog and update examples
waketzheng Dec 12, 2025
eed6bdb
fix: sqlite: avoid calling internal methods when initializing aiosqli…
donlon Dec 13, 2025
8912146
Update CHANGELOG.rst
donlon Dec 13, 2025
7570e09
Update CHANGELOG.rst
donlon Dec 13, 2025
ab57d5a
Fix codacy complaints
waketzheng Dec 14, 2025
e6f63b3
Rollback unnecessary changes
waketzheng Dec 14, 2025
f9270c5
Update version to 0.25.2
henadzit Dec 15, 2025
4cc3e02
Merge remote-tracking branch 'he/update-version' into feat-foreignkey…
waketzheng Dec 16, 2025
2946d8a
chore: upgrade deps
waketzheng Dec 16, 2025
217b073
Merge remote-tracking branch 'don/develop' into feat-foreignkey-to-model
waketzheng Dec 16, 2025
3a55f84
chore: fix ruff issue
waketzheng Dec 16, 2025
a2ef0fe
Merge remote-tracking branch 'upstream/develop' into feat-foreignkey-…
waketzheng Dec 16, 2025
c963cad
Merge branch 'develop' of github.com:tortoise/tortoise-orm into feat-…
waketzheng Dec 16, 2025
15cb996
docs: update changelog
waketzheng Dec 16, 2025
bc62b2f
Merge branch 'develop' of github.com:tortoise/tortoise-orm into feat-…
waketzheng Dec 20, 2025
01a9de2
Merge branch 'develop' of github.com:tortoise/tortoise-orm into feat-…
waketzheng Dec 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ Changelog
0.26.0 (unreleased)
-------------------

Changed
^^^^^
- feat: foreignkey to model type (#2027)

0.25
====

Expand Down
2 changes: 1 addition & 1 deletion examples/complex_filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Event(Model):
id = fields.IntField(primary_key=True)
name = fields.TextField()
tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events"
Tournament, related_name="events"
)
participants: fields.ManyToManyRelation["Team"] = fields.ManyToManyField(
"models.Team", related_name="events", through="event_team"
Expand Down
2 changes: 1 addition & 1 deletion examples/complex_prefetching.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Event(Model):
id = fields.IntField(primary_key=True)
name = fields.TextField()
tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events"
Tournament, related_name="events"
)
participants: fields.ManyToManyRelation["Team"] = fields.ManyToManyField(
"models.Team", related_name="events", through="event_team"
Expand Down
2 changes: 1 addition & 1 deletion examples/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Event(Model):
id = fields.IntField(primary_key=True)
name = fields.TextField()
tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events"
Tournament, related_name="events"
)
participants: fields.ManyToManyRelation["Team"] = fields.ManyToManyField(
"models.Team", related_name="events", through="event_team"
Expand Down
2 changes: 1 addition & 1 deletion examples/global_table_name_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class BlogPost(Model):
id = fields.IntField(primary_key=True)
title = fields.TextField()
author: fields.ForeignKeyRelation[UserProfile] = fields.ForeignKeyField(
"models.UserProfile", related_name="posts"
UserProfile, related_name="posts"
)

class Meta:
Expand Down
8 changes: 5 additions & 3 deletions examples/group_by.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
class Author(Model):
name = fields.CharField(max_length=255)

books: fields.ReverseRelation["Book"]


class Book(Model):
name = fields.CharField(max_length=255)
author: fields.ForeignKeyRelation[Author] = fields.ForeignKeyField(
"models.Author", related_name="books"
)
author: fields.ForeignKeyRelation[Author] = fields.ForeignKeyField(Author, related_name="books")
rating = fields.FloatField()

author_id: int


async def run():
await Tortoise.init(db_url="sqlite://:memory:", modules={"models": ["__main__"]})
Expand Down
4 changes: 2 additions & 2 deletions examples/pydantic/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Event(Model):
name = fields.TextField()
created_at = fields.DatetimeField(auto_now_add=True)
tournament: fields.ForeignKeyNullableRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events", null=True
Tournament, related_name="events", null=True
)
participants: fields.ManyToManyRelation["Team"] = fields.ManyToManyField(
"models.Team", related_name="events", through="event_team"
Expand All @@ -40,7 +40,7 @@ class Address(Model):
created_at = fields.DatetimeField(auto_now_add=True)

event: fields.OneToOneRelation[Event] = fields.OneToOneField(
"models.Event", on_delete=fields.OnDelete.CASCADE, related_name="address", primary_key=True
Event, on_delete=fields.OnDelete.CASCADE, related_name="address", primary_key=True
)

class Meta:
Expand Down
2 changes: 1 addition & 1 deletion examples/pydantic/early_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Event(Model):
name = fields.TextField()
created_at = fields.DatetimeField(auto_now_add=True)
tournament: fields.ForeignKeyNullableRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events", null=True
Tournament, related_name="events", null=True
)

class Meta:
Expand Down
2 changes: 1 addition & 1 deletion examples/pydantic/tutorial_3.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Event(Model):
created_at = fields.DatetimeField(auto_now_add=True)

tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events", description="The Tournament this happens in"
Tournament, related_name="events", description="The Tournament this happens in"
)


Expand Down
2 changes: 1 addition & 1 deletion examples/pydantic/tutorial_4.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Event(Model):
created_at = fields.DatetimeField(auto_now_add=True)

tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events", description="The Tournament this happens in"
Tournament, related_name="events", description="The Tournament this happens in"
)

class Meta:
Expand Down
5 changes: 3 additions & 2 deletions examples/relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ class Event(Model):
id = fields.IntField(primary_key=True)
name = fields.TextField()
tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events"
Tournament, related_name="events"
)
# class Team does not defined before Event, so we have to use '{app}.{model_class}'
participants: fields.ManyToManyRelation["Team"] = fields.ManyToManyField(
"models.Team", related_name="events", through="event_team"
)
Expand All @@ -40,7 +41,7 @@ class Address(Model):
street = fields.CharField(max_length=128)

event: fields.OneToOneRelation[Event] = fields.OneToOneField(
"models.Event", on_delete=fields.OnDelete.CASCADE, related_name="address", primary_key=True
Event, on_delete=fields.OnDelete.CASCADE, related_name="address", primary_key=True
)

def __str__(self):
Expand Down
4 changes: 2 additions & 2 deletions examples/relations_with_unique.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ class Student(Model):
id = fields.IntField(primary_key=True)
name = fields.TextField()
school: fields.ForeignKeyRelation[School] = fields.ForeignKeyField(
"models.School", related_name="students", to_field="id"
School, related_name="students", to_field="id"
)


class Principal(Model):
id = fields.IntField(primary_key=True)
name = fields.TextField()
school: fields.OneToOneRelation[School] = fields.OneToOneField(
"models.School", on_delete=fields.OnDelete.CASCADE, related_name="principal", to_field="id"
School, on_delete=fields.OnDelete.CASCADE, related_name="principal", to_field="id"
)


Expand Down
2 changes: 1 addition & 1 deletion examples/schema_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Event(Model):
id = fields.IntField(primary_key=True, description="Event ID")
name = fields.CharField(max_length=255, unique=True)
tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField(
"models.Tournament", related_name="events", description="FK to tournament"
Tournament, related_name="events", description="FK to tournament"
)
participants: fields.ManyToManyRelation["Team"] = fields.ManyToManyField(
"models.Team",
Expand Down
11 changes: 11 additions & 0 deletions tests/test_relations.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import subprocess # nosec

from tests.testmodels import (
Address,
Author,
Expand Down Expand Up @@ -501,3 +503,12 @@ async def test_reverse_relation_create_fk_errors_for_unsaved_instance(self):
await tournament.events.create(name="Test Event")

self.assertIn("hasn't been instanced", str(cm.exception))

@test.requireCapability(dialect="sqlite")
async def test_recursive(self) -> None:
file = "examples/relations_recursive.py"
r = subprocess.run(["python", file], capture_output=True, text=True) # nosec
assert not r.stderr
output = r.stdout
s = "2.1. Second H2 (to: ) (from: 2.2. Third H2, Loose, 1.1. First H2)"
self.assertIn(s, output)
Loading