2015-10-04 23 views
6

Ho un modello in questo mododjango 1.7 join esterno sinistro

class Job(models.Model): 
    description = models.CharField(max_length=255) 
    user = models.ForeignKey(User) 
    date = models.DateField() 
    slot = models.CharField(max_length=10, choices=SLOT_CHOICES) 
    location = models.ForeignKey(Location)   
    objects = JobManager() 
    searches = geomodels.GeoManager() 

    class Meta: 
     verbose_name_plural = "Job" 
     unique_together = ('date', 'slot', 'user') 

    def __str__(self): 
     return "{0}-{1}".format(self.user.first_name, self.date) 

class Applied(models.Model): 
    user = models.ForeignKey(User) 
    job = models.ForeignKey(Job, null=True, blank=True) 
    action_taken = models.BooleanField(default=False) 
    is_declined = models.BooleanField(default=False) 

    class Meta: 
     verbose_name_plural = "Job Applications" 
     unique_together = ('user', 'job',) 

voglio cercare tutti i posti di lavoro tra un intervallo di date e mostrare se un utente può applicare, già applicato o è stata rifiutata. Le informazioni dell'applicazione sono nel modello applicato.

jobs = Job.searches.filter(**kwargs)\ 
     .filter(date__range=(date_from, date_to), 
       visibility=VisibilityStatus.PUBLIC, 
       status=JobStatus.AVAILABLE)\ 
     .prefetch_related('applied_set')\ 
     .select_related('user__surgeryprofile__location')\ 
     .order_by('date') 

Ma non riesco a farlo funzionare, non sta facendo un join sinistro sulla tabella applicata nel database. qualsiasi suggerimento su come farlo funzionare.

Grazie

+0

Perdonami per la domanda, ma non sarebbe sufficiente un join interno? – e4c5

+0

Inner join porterà solo le righe che esistono in entrambe le tabelle, voglio un left out join come voglio tutte le righe dalla tabella di job tra l'intervallo di date e le righe dalla tabella applicata se l'utente ha già fatto domanda per quel lavoro e se è stato rifiutato. –

+1

Il tuo codice dovrebbe darti il ​​risultato giusto (lavori filtrati con un_set_peso che potrebbe essere vuoto) anche se non ci sono join. "prefetch_related nella maggior parte dei casi verrà implementato utilizzando una query SQL che utilizza l'operatore" IN "." https://docs.djangoproject.com/en/1.7/ref/models/querysets/#prefetch-related – JimmyYe

risposta

4

Django ORM eseguire LEFT OUTER JOIN quando FK'S sono NULLABLE.

Soluzione: Basta aggiungere null=True su questo FK job = models.ForeignKey(Job, null=True, blank=True) si desidera unirsi a ottenere i valori nulli e Django cambierà INNER JOIN da LEFT OUTER JOIN.

Questo è logico, poiché il join esterno sinistro ha senso quando le tabelle di destinazione potrebbero non avere una corrispondenza esatta prevalente nella tabella più a sinistra nella query.

UPDATE: funziona solo per il campo ForeignKey e select_related, non per ManyToMany con prefetch_related.

possibile soluzione per i campi M2M:

  1. debug del codice SQL generato (debug = True, la registrazione con logger 'django.db.backends')
  2. copiarlo e sostituire INNER JOIN con SINISTRA outer join
  3. Eseguire Model.objects.raw (sql_with_left_join)

https://docs.djangoproject.com/en/1.8/topics/db/sql/#performing-raw-sql-queries

Questo dovrebbe dare gli stessi risultati di prima, ma aggiungere quei lavori che non hanno M2M con applicato.

UPDATE2: personalizzato unisce a Django per le versioni < = 1.5, non funziona su 1.6 +

Trovato in questo blog entry: https://www.caktusgroup.com/blog/2009/09/28/custom-joins-with-djangos-queryjoin/

Da StackOverflow: https://stackoverflow.com/a/12943120/1090700

+0

applausi, questo ha senso. Ci proveremo. –

+0

Ho aggiornato il modello come da suggerimento ma non funziona ancora. Non sto ottenendo alcun riferimento alla tabella applicata nella query. –

+0

Ciò è probabilmente dovuto a ManyToMany, quello che stavo dicendo era per select_related e ForeignKey, dopo averlo testato, controllato che in M2M non lo stia facendo. Probabilmente dovresti creare un Job.objects.raw se vuoi saltare M2M con un LEFT OUTER JOIN (basta eseguire il debug di SQL generato e sostituire INNER JOIN di LEFT OUTER JOIN): https://docs.djangoproject.com/en /1.8/topics/db/sql/#performing-raw-sql-queries – danigosa

Problemi correlati