Sto usando Django v1.9.4 con PostgreSQL 9.2.14 dietro. Con i seguenti modelli:Come attraversare una GenericForeignKey in 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')
Creare alcuni casi per dimostrare il mio problema:
>>> 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'
Non posso attraversare la GFK in Django, cercando di filtro solleva un'eccezione con un messaggio che suggerisce di aggiungere il GenericRelation
. Ma l'utilizzo della relazione generica, tramite il nome della query correlata bars
, non funziona in modo affidabile. Per esempio:
>>> [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?
Che cosa sto facendo di sbagliato?
cautelativa nota ai futuri lettori: Templating related_query_name
su GenericRelation
non funziona correttamente su Django 1.9.
Aggiunto in Django 1.10 era related_query_name now supports app label and class interpolation using the '%(app_label)s' and '%(class)s' strings, dopo che fix per #25354 è stato unito.
Se sei su Django 1.10, puoi andare avanti e mettere il GenericRelation
sulla classe base astratta e modello come related_query_name='%(app_label)s_%(class)s'
per garantire l'univocità tra le sottoclassi.
OK così sembra essere un limitazione dovuta all'unione di sql. Ma per gli esempi nella mia domanda, perché django consente le domande a tutti? Non dovrebbe piuttosto sollevare un'eccezione, piuttosto che restituire risultati errati? – wim
Sì, sembra un bug, non penso che dovrebbe permetterti di fare queste domande. Potresti forse aggiungere l'SQL generato da quelle query alla tua domanda? – koniiiik
Ho giocato un po 'con la tua soluzione e ho trovato un'altra cosa interessante, potrebbe non essere necessario inserire il campo 'GenericRelation' su ogni sottoclasse con un unico' related_query_name'. Puoi effettivamente lasciarlo sulla classe base e metterlo a modello come 'related_query_name = '% (app_label) s _% (class) s'' per garantire l'unicità. – wim