Skip to content

Commit bdc3225

Browse files
committed
Fix filtering by FK instance to use to_field instead of pk
1 parent 8c12adc commit bdc3225

3 files changed

Lines changed: 19 additions & 1 deletion

File tree

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Added
2020

2121
Fixed
2222
^^^^^
23+
- Filtering by a related model instance on a ``ForeignKeyField``/``OneToOneField`` declared with a non-primary-key ``to_field`` now uses the ``to_field`` value instead of the instance's primary key, so the generated query targets the correct column. (#2225)
2324
- ``MigrationRecorder`` now uses parameterized queries; fixes MariaDB/MySQL rejecting ISO-8601 ``applied_at`` values. (#2132)
2425
- ``db_default`` on ``ForeignKeyField``/``OneToOneField`` now propagates to the underlying ``<fk>_id`` column, so ``CREATE TABLE`` emits the ``DEFAULT`` clause for FK columns. (#2199)
2526
- ``MigrationRecorder`` no longer emits tortoise's own ``pk`` field ``DeprecationWarning`` when applying migrations; it now builds its bookkeeping model with ``primary_key=True``. (#2203)

tests/test_relations_with_unique.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,19 @@ async def test_relation_with_unique(db):
4444
assert fetched_principal.name == "Sang-Heon Jeon3"
4545
fetched_school = await School.filter(name="School1").prefetch_related("principal").first()
4646
assert fetched_school.name == "School1"
47+
48+
49+
@pytest.mark.asyncio
50+
async def test_filter_by_fk_instance_uses_to_field(db):
51+
# https://github.com/tortoise/tortoise-orm/issues/2225
52+
# School's primary key is `uuid`, but Student.school points to to_field="id"
53+
# (a non-PK unique field). Filtering by a School instance must use the
54+
# `to_field` value (school.id), not the primary key (school.uuid).
55+
school = await School.create(id=42, name="School1")
56+
await Student.create(name="Sang-Heon Jeon1", school=school)
57+
58+
assert school.pk != school.id
59+
60+
found = await Student.filter(school=school).first()
61+
assert found is not None
62+
assert found.name == "Sang-Heon Jeon1"

tortoise/expressions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,8 @@ def _get_actual_filter_params(
439439
):
440440
field_object = resolve_context.model._meta.fields_map[key]
441441
filter_key = cast(str, field_object.source_field)
442-
filter_value = getattr(value, "pk", value)
442+
to_field_name = field_object.to_field_instance.model_field_name
443+
filter_value = getattr(value, to_field_name, value)
443444
elif key in resolve_context.model._meta.m2m_fields:
444445
filter_value = getattr(value, "pk", value)
445446
elif (

0 commit comments

Comments
 (0)