2015-10-04 106 views
6

我有像這樣的Django 1.7左外連接

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

我要搜索所有日期範圍之間的工作,並顯示用戶是否可以申請一個模型,已申報或已被拒絕。應用程序信息在應用程序模型中。

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

但我無法得到它的工作,它不在數據庫中對應用表進行左連接。任何建議如何讓它工作。

感謝

+0

請原諒我問,但內部連接不會足夠嗎? – e4c5

+0

內部聯接只會帶來兩個表中存在的行,我想要一個左側聯接,因爲我希望日期範圍和應用表中的行之間的作業表中的所有行如果用戶已經申請了該作業並且它已經下降。 –

+1

即使沒有連接,您的代碼應該會給您正確的結果(已過濾的作業可能爲空的applied_set)。 「在大多數情況下,prefetch_related將使用使用'IN'運算符的SQL查詢來實現。」 https://docs.djangoproject.com/en/1.7/ref/models/querysets/#prefetch-related – JimmyYe

回答

4

Django的ORM執行LEFT OUTER JOIN時FK的是NULLABLE

解決方案:只需添加null=True這個FK job = models.ForeignKey(Job, null=True, blank=True)你想加入越來越空值和Django會改變INNER通過LEFT OUTER JOIN JOIN。

這是合乎邏輯的,因爲如果目標表可能沒有與查詢中最左邊的表格完全匹配的準確匹配,則左外部聯接有意義。

UPDATE:這隻適用於ForeignKey字段和select_related,不適用於具有prefetch_related的ManyToMany字段。

爲M2M字段可能的解決方案:

  1. 調試生成(DEBUG =真,用記錄儀記錄 'django.db.backends')
  2. 複製它和替換INNER與LEFT JOIN的SQL OUTER JOIN
  3. 執行Model.objects.raw(sql_with_left_join)

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

這應該會得到與以前相同的結果,但將那些沒有M2M的作業添加到應用程序中。

UPDATE2:自定義在Django JOINS爲<版本= 1.5,不工作的1.6+

在這個博客條目中找到:https://www.caktusgroup.com/blog/2009/09/28/custom-joins-with-djangos-queryjoin/

從StackOverflow的:https://stackoverflow.com/a/12943120/1090700

+0

歡呼聲,這是有道理的。會放棄它。 –

+0

我根據您的建議更新了模型,但仍然無法正常工作。我沒有在查詢中獲得對應用表的任何引用。 –

+0

這可能是由於ManyToMany,我說的是select_related和ForeignKey,在測試之後,檢查了在M2M中沒有這樣做。如果你想用一個LEFT OUTER JOIN跳過M2M(只需調試生成的SQL並用LEFT OUTER JOIN替換INNER JOIN),你可能必須創建一個Job.objects.raw:https://docs.djangoproject.com/en /1.8/topics/db/sql/#performing-raw-sql-queries – danigosa