2016-05-19 8 views
5

ich ein Modell mit einfachen Beziehung habenDjango prefetch_related - Filter mit or-Klausel aus verschiedenen Tabellen

class Tasks(models.Model): 
    initiator = models.ForeignKey(User, on_delete = models.CASCADE) 

class TaskResponsiblePeople(models.Model): 
    task = models.ForeignKey('Tasks') 
    auth_user = models.ForeignKey(User) 

Und ich brauche ein Analogon von einer SQL-Abfrage zu schreiben, wie folgt:

select a.initiator, b.auth_user 
from Tasks a 
inner join TaskResponsiblePeople b 
on TaskResponsiblePeople.task_id = task.id 
where Tasks.initiator = 'value A' OR TaskResponsiblePeople.auth_user = 'value B' 

Die Problem ist, dass die OR-Anweisung zwei verschiedene Tabellen behandelt und ich habe keine Ahnung von der richtigen Django-Syntax, um die oben genannte Raw-SQL-Abfrage zu mimikieren. Hilf mir bitte!

UPDATE 1

Nach der unten angegebenen Antwort, verwende ich den folgenden Code:

people = TaskResponsiblePeople.objects.filter(Q(task__initiator = request.user.id)|Q(auth_user = request.user.id)).select_related('auth_user') 
print people.query 
# The result of the print copy-pasted from console 
# SELECT * FROM `task_responsible_people` 
# LEFT OUTER JOIN `tasks` ON (`task_responsible_people`.`task_id` = `tasks`.`id`) 
# LEFT OUTER JOIN `auth_user` T4 
# ON (`task_responsible_people`.`auth_user_id` = T4.`id`) 
# WHERE (`tasks`.`initiator_id` = 7 OR  
# 'task_responsible_people`.`auth_user_id` = 7) 

tasks = Tasks.objects.prefetch_related(
       Prefetch('task_responsible_people', queryset=people, to_attr='people')) 

jedoch in der letzten resultset kann ich noch Aufzeichnungen sehen, wo weder Initiator noch auth_user sind gleich zu request.user (in diesem Fall gleich 7) Ich vermeide die Verwendung von ".values" wegen der möglichen Notwendigkeit, das Queryset in json zu serialisieren und zu transformieren.

+0

und Sie wollen beide 'Tasks' und' TaskRespons "iblePeople" in dem resultierenden Abfrage-Set? – AKS

+0

Ja, genau. Ich habe die obige Frage bearbeitet, um dies zu verdeutlichen. –

+0

Schauen Sie sich meine Antwort an. Es sollte die richtige Abfrage generieren. – AKS

Antwort

2

Ich denke, man kann es auf diese Weise tun, wenn Sie nur diese bestimmte Spalten wollen:

from django.db.models import Q 

qs = Tasks.objects.filter(Q(initiator=userA) | Q(taskresponsiblepeople__auth_user=userB))\ 
      .values('initiator', 'taskresponsiblepeople__auth_user') 

die erzeugte Abfrage Um zu untersuchen, die Sie betrachten können:

print(qs.query) 

ich das nicht haben Modelle in meiner Datenbank, aber es sollte eine Abfrage wie folgt erzeugen:

SELECT "tasks"."initiator_id", "taskresponsiblepeople"."auth_user_id" 
    FROM "tasks" LEFT OUTER JOIN "taskresponsiblepeople" 
    ON ("tasks"."id" = "taskresponsiblepeople"."tasks_id") 
    WHERE ("tasks"."initiator_id" = userA_id 
      OR "taskresponsiblepeople"."auth_user_id" = userB_id)) 
+0

Siehe den letzten Teil von Update 2 in meiner Frage –

+0

Nun !, Sie ändern den Umfang der Frage mit der Zeit, während der Umfang der SQL-Abfrage, die Sie gebucht haben, geringer war. Wenn Sie sich meinen ersten Kommentar oben ansehen, fragte ich speziell, ob Sie die Objekte selbst haben wollten. – AKS

+0

Ich möchte nur die Abfrage durch die Kombination von Filter, select_related oder prefetch_related erhalten, ohne Werte zu verwenden. –

Verwandte Themen