2009-07-10 10 views
2

Considérez les modèles:Django - queryset couvrant les relations nulles utilisant Q

#Models 
class A(models.Model): 
    fieldOfA = models.CharField(max_length = 4) 
class B(models.Model): 
    fieldOfB = models.CharField(max_length = 4) 
class C(models.Model): 
    classA = models.ForeignKey(A, blank=True, null=True) 
    classB = models.ForeignKey(B, blank=True, null=True) 

Quand je crée des objets de C, je me assurer qu'un objet a soit une relation CLASSA ou ClassB. Je recherche un simple jeu de requête, qui me donne des objets de C pour des valeurs fieldOfA spécifiques ou fieldOfB spécifiques.

J'ai essayé ceci, mais cela échoue (renvoie [], malgré des résultats valides).

#Views - assume double underscore in the query 
from django.db.models import Q 
my_query = C.objects.filter(Q(classA _ _isnull = False, classA _ _fieldOfA = 'foo') | Q(classB _ _isnull = False, classB _ _fieldOfB = 'foo')) 

Le problème que je vois est le '|' c'est l'appliqué. Deux différents querysets pour classA et classB fonctionnent bien. D'une manière ou d'une autre, je pourrais appliquer un simple jeu de requête pour que cela fonctionne? Ou pire, un moyen de fusionner les querysets individuels.

Répondre

2

Si vous pouvez être sûr qu'un C a un A ou un B mais jamais les deux, vos contraintes isnull sont redondantes. Que se passe-t-il si vous exécutez ce qui suit?

C.objects.filter(Q(classA__fieldOfA = 'foo') | Q(classB__fieldOfB = 'foo')) 

Si cela ne fonctionne toujours pas, exécutez manage.py shell et après l'exécution de la requête ci-dessus (assurant que settings.DEBUG est True, vérifiez le SQL généré au-dessus avec

>>> from django.db import connection 
>>> connection.queries() 

Que voyez-vous?

+0

Malheureusement, l'élimination de la redondance n'a pas aidé. Le SQL a deux 'JOINT OUTER OUTER' pour les deux Q (suivi intérieurement par un INNER JOIN). Le deuxième Q ne devrait-il pas avoir un DROIT EXTERNE? Les valeurs fieldB ne sont pas restaurées. Merci pour l'aide cependant. Je chaînais (fusionnant, d'une certaine manière) les deux querysets maintenant, ce qui fonctionne aussi pour moi. En utilisant cet extrait de code - http://www.djangosnippets.org/snippets/1103/ – tjazz

2

en fait, vous pouvez combiner QuerySet s de la même manière comme ceci:.

C.objects.filter(classA__fieldOfA='foo') | C.objects.filter(classB__fieldOfB='foo') 
Questions connexes