Opened 12 months ago

Closed 12 months ago

Last modified 11 months ago

#34594 closed New feature (wontfix)

KT doesn’t work across foreign keys

Reported by: Roman Odaisky Owned by: nobody
Component: Database layer (models, ORM) Version: 4.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Assuming

class Parent(Model):
    data = JSONField()

class Child(Model):
    parent = ForeignKey(Parent)

the expressions

Parent.objects.annotate(x=F("data__some_string")).first().x
Parent.objects.annotate(x=KT("data__some_string")).first().x
Parent.objects.first().data["some_string"]

all return the same value. So far, so good. However, in the following F works but KT doesn’t:

Child.objects.annotate(x=F("parent__data__some_string"))
Child.objects.annotate(x=KT("parent__data__some_string"))

The problem is in the SQL that KT generates: ("parent"."id" #>> ARRAY['data','some_string']) AS "x", which, it seems, is the result of KeyTextTransform.from_lookup taking all the double-underscore-separated parts of the argument of KT to mean JSON lookups and not other possible lookups such as foreign keys.

Please fix by using the same mechanisms F uses in this case.

Change History (2)

in reply to:  description comment:1 by Mariusz Felisiak, 12 months ago

Resolution: wontfix
Status: newclosed
Type: BugNew feature

The problem is in the SQL that KT generates: ("parent"."id" #>> ARRAY['data','some_string']) AS "x", which, it seems, is the result of KeyTextTransform.from_lookup taking all the double-underscore-separated parts of the argument of KT to mean JSON lookups and not other possible lookups such as foreign keys.

Thanks for the report, however, it works exactly as documented "You can use the double underscore notation in lookup to chain dictionary key and index transforms.", so it's not a bug but a new feature request. As far as I'm aware we don't want to complicate it, and you can annotate nested JSONField to make it work, e.g.

Child.objects.annotate(data=F("parent__data"), x=KT("data__some_string"))

You can start a discussion on DevelopersMailingList if you don't agree.

comment:2 by Natalia Bidart, 11 months ago

I think #34667 is a duplicate of this one.

Note: See TracTickets for help on using tickets.
Back to Top