I'm using Django v1.9.4 with PostgreSQL 9.2.14 behind. With the following models:
from django.db import models from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey from django.contrib.contenttypes.models import ContentType class Foo(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() bar = GenericForeignKey('content_type', 'object_id') class Bar(models.Model): foos = GenericRelation(Foo, related_query_name='bars') class Meta: abstract = True class BarX(Bar): name = models.CharField(max_length=10, default='bar x') class BarY(Bar): name = models.CharField(max_length=10, default='bar y')
Create some instances to demonstrate my problem:
>>> bar_x = BarX.objects.create() >>> bar_y = BarY.objects.create() >>> foo1 = Foo.objects.create(bar=bar_x) >>> foo2 = Foo.objects.create(bar=bar_y) >>> foo1.bar.name u'bar x' >>> foo2.bar.name u'bar y'
I can't traverse the GFK in django, attempting to filter raises an exception with a message suggesting to add the GenericRelation
. But using the generic relation, through related query name bars
, is not working reliably. For example:
>>> [foo.bar.name for foo in Foo.objects.all()] [u'bar x', u'bar y'] # in a pure python loop, it's working >>> Foo.objects.filter(bar__name='bar x') FieldError: Field 'bar' does not generate an automatic reverse relation and therefore cannot be used for reverse querying. If it is a GenericForeignKey, consider adding a GenericRelation. >>> Foo.objects.values_list('bars__name', flat=1) [None, u'bar y'] # but why None is returned in here? >>> Foo.objects.filter(bars__name='bar x') [] # why no result here? >>> Foo.objects.filter(bars__name='bar y') [<Foo: Foo object>] # but this one works?
What am I doing wrong?
Cautionary note to future readers: Templating related_query_name
on GenericRelation
doesn't work properly on Django 1.9.
Added in Django 1.10 was related_query_name now supports app label and class interpolation using the '%(app_label)s' and '%(class)s' strings, after the fix for #25354 was merged.
If you're on Django 1.10, you can go ahead and put the GenericRelation
on the abstract base class and template it like related_query_name='%(app_label)s_%(class)s'
to ensure uniqueness across the subclasses.