Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#27414 closed Cleanup/optimization (fixed)

Document that aliasing ForeignKey fields in F expressions returns pk values, not model instances

Reported by: MikiSoft Owned by: Jop Reyntjes
Component: Documentation Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by MikiSoft)

Assuming that Relationship consists of from_person and to_person ForeignKey fields (which point to User), here's an simple example of showing the actual problem:

>> results = Relationship.objects.all().annotate(target=F('to_person'))
>> results[0].from_person
<User: second>
>> results[0].target
3

So, it doesn't work as expected. It should just rename the field, not convert it to the integer type.
The same happens with complex annotations when using conditional expressions (i.e. Case statements). I've even tried like this:

.annotate(
        person= \
                Case( \
                        When( \
                                to_person__in=friends, \
                                then=F('to_person') \
                        ), \
                        default=F('from_person'),  \
                        output_field=ForeignKey('User') \
                ), \
        target= \
                Case( \
                        When( \
                                to_person__in=friends, \
                                then=F('from_person') \
                        ), \
                        default=F('to_person'), \
                        output_field=ForeignKey('User') \
                ) \
)

But it still doesn't work. So that's the reason why I think that this is a bug, as I haven't found any explanation for this behavior. In my case in aliased fields I would need objects to be returned, not only IDs of them, therefore I don't know how to solve this.

Change History (7)

comment:1 by MikiSoft, 7 years ago

Description: modified (diff)
Summary: Aliasing ForeignKey fields return integer value, not objectAliasing ForeignKey fields return integer values, not object

comment:2 by Tim Graham, 7 years ago

Component: Database layer (models, ORM)Documentation
Summary: Aliasing ForeignKey fields return integer values, not objectDocument that aliasing ForeignKey fields in F expressions returns pk values, not model instances
Triage Stage: UnreviewedAccepted
Type: BugCleanup/optimization

I'm not sure if that can be changed easily, for one, it will be backwards-incompatible for anyone relying on the current behavior. Feel free to get other opinions on the DevelopersMailingList. Qualifying as a documentation change for now.

It would be nice to describe your use case in some more detail to decide whether or not Django must provide a way for aliasing to return instances.

comment:3 by Josh Smeaton, 7 years ago

(I lost the original comment I wrote here so here's a condensed version).

Using a ForeignKey as the output_field is an interesting idea that I hadn't considered, and would solve any backward compatibility issues. I don't know what the difficulty would be, but F fields already have access to the query to add necessary joins. I doubt foreign key fields are added to joins right yet, but __underscore relationships do add joins to the query. The next hard thing would be reconstructing the object.

All of this sounds doable though.

Last edited 7 years ago by Tim Graham (previous) (diff)

comment:4 by Jop Reyntjes, 7 years ago

Owner: changed from nobody to Jop Reyntjes
Status: newassigned

comment:5 by Simon Charette, 7 years ago

Has patch: set
Version: 1.10master

comment:6 by Tim Graham <timograham@…>, 7 years ago

Resolution: fixed
Status: assignedclosed

In f8fab6f9:

Fixed #27414 -- Doc'd that F() expressions on relations return pk values.

comment:7 by Tim Graham <timograham@…>, 7 years ago

In 89d9601:

[1.10.x] Fixed #27414 -- Doc'd that F() expressions on relations return pk values.

Backport of f8fab6f90233c7114d642dfe01a4e6d4cb14ee7d from master

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