2010-10-15 4 views
5

Je souhaite filtrer un jeu de requête en déterminant si une sous-requête précise renvoie des résultats. En SQL, cela peut ressembler à ceci:Comment "filtrer" par "existe" dans Django?

SELECT * FROM events e WHERE EXISTS 
    (SELECT * FROM tags t WHERE t.event_id = e.id AND t.text IN ("abc", "def")) 

En d'autres termes, récupérez tous les événements qui sont étiquetés avec l'une des étiquettes spécifiées.

Comment est-ce que je pourrais exprimer cela en utilisant l'API QuerySet de Django sur les modèles Event et Tag?

Répondre

12

Vous pouvez faire quelque chose comme ceci:

q = Event.objects.filter(tag__text__in = ['abc', 'def']) 

En supposant qu'il ya un ForeignKey de Tag à Event.

Explication: Vous filtrez les objets Event en fonction d'un critère spécifique. A l'aide de la syntaxe de double trait de soulignement, vous accédez à l'attribut text des instances Tag puis à la condition IN. Vous n'avez pas à vous soucier de la jointure sur la clé étrangère; Django le fait pour vous dans les coulisses. Si vous êtes curieux de voir la requête générée, vous pouvez l'imprimer:

print q.query 
+0

Merci Manoj, il me semble souvent oublier d'essayer le « évidente » dans Django et commencer à penser à quelque chose qui est assez compliqué. –

5

solution de Manoj peut causer un problème quand il y a plusieurs balises pour un événement. La jointure interne SQL renvoie toutes les lignes afin que les événements puissent avoir des résultats en double, la solution consiste à ajouter la méthode distincte.

q = Event.objects.filter(tag__text__in = ['abc', 'def']).distinct()

Questions connexes