I must be really misunderstanding something with the GenericRelation
field from Django's content types framework.
To create a minimal self contained example, I will use the polls example app from the tutorial. Add a generic foreign key field into the Choice
model, and make a new Thing
model:
class Choice(models.Model):
...
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
thing = GenericForeignKey('content_type', 'object_id')
class Thing(models.Model):
choices = GenericRelation(Choice, related_query_name='things')
With a clean db, synced up tables, and create a few instances:
>>> poll = Poll.objects.create(question='the question', pk=123)
>>> thing = Thing.objects.create(pk=456)
>>> choice = Choice.objects.create(choice_text='the choice', pk=789, poll=poll, thing=thing)
>>> choice.thing.pk
456
>>> thing.choices.get().pk
789
So far so good - the relation works in both directions from an instance. But from a queryset, the reverse relation is very weird:
>>> Choice.objects.values_list('things', flat=1)
[456]
>>> Thing.objects.values_list('choices', flat=1)
[456]
Why the inverse relation gives me again the id from the thing
? I expected instead the primary key of the choice, equivalent to the following result:
>>> Thing.objects.values_list('choices__pk', flat=1)
[789]
Those ORM queries generate SQL like this:
>>> print Thing.objects.values_list('choices__pk', flat=1).query
SELECT "polls_choice"."id" FROM "polls_thing" LEFT OUTER JOIN "polls_choice" ON ( "polls_thing"."id" = "polls_choice"."object_id" AND ("polls_choice"."content_type_id" = 10))
>>> print Thing.objects.values_list('choices', flat=1).query
SELECT "polls_choice"."object_id" FROM "polls_thing" LEFT OUTER JOIN "polls_choice" ON ( "polls_thing"."id" = "polls_choice"."object_id" AND ("polls_choice"."content_type_id" = 10))
The Django docs are generally excellent, but I can't understand why the second query or find any documentation of that behaviour - it seems to return data from the wrong table completely?