2016-05-19 12 views
5

Ho un modello con semplice relazioneDjango prefetch_related - filtro con o clausola da tabelle diverse

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) 

E ho bisogno di scrivere un analogo di una query SQL come segue:

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' 

Il il problema è che l'istruzione OR si occupa di due diverse tabelle e non ho idea della giusta sintassi Django per mimare la query raw-SQL sopra indicata. Aiutami ad uscire!

UPDATE 1

Secondo la risposta qui sotto-dichiarato, io uso il seguente codice:

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')) 

Tuttavia, nel set di risultati finale riesco ancora a vedere i record in cui né iniziatore né auth_user sono uguale a request.user (uguale a 7 in questo caso) Evito di usare ".values" a causa della potenziale necessità di serializzare e trasformare il queryset in json.

+0

E, si desidera sia "Task" che "TaskRespons" iblePeople' nel queryset risultante? – AKS

+0

Sì, esattamente. Ho modificato la domanda sopra per riflettere questo. –

+0

Dai un'occhiata alla mia risposta. Dovrebbe generare la query corretta. – AKS

risposta

2

Penso che si possa farlo in questo modo, se si desidera solo quelle colonne specifiche:

from django.db.models import Q 

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

per esaminare la query generato si può guardare:

print(qs.query) 

non ho il modelli nel mio database ma dovrebbe generare una query simile al seguente:

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

Vedere l'ultima parte dell'aggiornamento 2 nella mia domanda –

+0

Bene !, si sta modificando l'ambito della domanda con il tempo mentre l'ambito della query SQL che hai postato era minore. Se guardi il mio primo commento sopra, ho chiesto espressamente se volevi gli oggetti stessi? – AKS

+0

Voglio solo ottenere la query dalla combinazione di filtro, select_related o prefetch_related senza utilizzare valori. –

Problemi correlati