Я использую Django v1.9.4 с PostgreSQL 9.2.14 позади. С помощью следующих моделей:Как проехать GenericForeignKey в Django?
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')
Создайте несколько экземпляров, чтобы продемонстрировать мою проблему:
>>> 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'
Я не могу пересечь GFK в Джанго, пытаясь фильтр вызывает исключение с сообщением предлагая добавить GenericRelation
. Но использование общего отношения, связанное с запросом имя bars
, не работает надежно. Например:
>>> [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?
Что я делаю неправильно?
Cautionary примечание к будущим читателям: Шаблонирования related_query_name
на GenericRelation
не работают должным образом на Django 1.9.
Добавлено в Django 1.10 было related_query_name now supports app label and class interpolation using the '%(app_label)s' and '%(class)s' strings, после того как fix для #25354 было слито.
Если вы находитесь на Django 1.10, вы можете пойти и поставить GenericRelation
на абстрактный базовый класс и шаблон, как related_query_name='%(app_label)s_%(class)s'
, чтобы обеспечить уникальность в подклассах.
ОК, так что, как представляется, ограничение из-за соединения sql. Но для примеров в моем вопросе, почему django разрешает запросы вообще? Разве это не должно скорее вызвать исключение, чем вернуть неверные результаты? – wim
Да, это похоже на ошибку, я не думаю, что это должно позволить вам делать такие запросы. Не могли бы вы добавить SQL-запрос, сгенерированный этими запросами, на ваш вопрос? – koniiiik
Я немного поиграл с вашим решением и нашел еще одну интересную вещь, возможно, нет необходимости помещать поле «GenericRelation» в каждом подклассе с уникальным 'related_query_name'. Вы можете оставить его в базовом классе и создать его как 'related_query_name = '% (app_label) s _% (класс) s'' для обеспечения уникальности. – wim