【问题标题】:django 1.7 left outer joindjango 1.7 左外连接
【发布时间】:2016-01-01 10:31:00
【问题描述】:

我有一个这样的模型

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

但我无法让它工作,它没有对数据库中的应用表进行左连接。任何如何让它工作的建议。

谢谢

【问题讨论】:

  • 请原谅我的提问,但内部连接不够吗?
  • 内连接只会带来两个表中存在的行,我想要一个左连接,因为如果用户已经应用,我想要日期范围和应用表中的行之间的作业表的所有行对于那个工作,如果它被拒绝了。
  • 即使没有连接,您的代码也应该为您提供正确的结果(带有可能为空的应用集的过滤作业)。 “在大多数情况下,prefetch_related 将使用使用‘IN’运算符的 SQL 查询来实现。” docs.djangoproject.com/en/1.7/ref/models/querysets/…
  • 虽然不工作,正在生成的查询甚至没有对应用表的任何引用。

标签: django django-queryset django-1.7


【解决方案1】:

当 FK 为 NULLABLE 时,Django ORM 执行 LEFT OUTER JOIN。

解决方案:只需在您希望加入的 FK job = models.ForeignKey(Job, null=True, blank=True) 上添加 null=True 以获取空值,Django 会将 INNER JOIN 更改为 LEFT OUTER JOIN。

这是合乎逻辑的,因为当目标表可能与查询中最左边的表不完全匹配时,左外连接才有意义。

更新:这仅适用于 ForeignKey 字段和 select_related,不适用于具有 prefetch_related 的 ManyToMany 字段。

M2M 领域的可能解决方案:

  1. 调试生成的 SQL(DEBUG=True,使用 logger 'django.db.backends' 进行日志记录)
  2. 复制它并将 INNER JOIN 替换为 LEFT 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 的 Job。

UPDATE2:Django 中的自定义 JOINS 版本

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

来自 StackOverflow:https://stackoverflow.com/a/12943120/1090700

【讨论】:

  • 我已按照您的建议更新了模型,但仍然无法正常工作。我在查询中没有得到任何对应用表的引用。
  • 这可能是由于ManyToMany,我说的是select_related和ForeignKey,经过测试,检查M2M没有这样做。如果您想使用 LEFT OUTER JOIN 跳过 M2M(只需调试生成的 SQL 并将 INNER JOIN 替换为 LEFT OUTER JOIN),您可能必须创建一个 Job.objects.raw:docs.djangoproject.com/en/1.8/topics/db/sql/…
猜你喜欢
  • 2016-10-29
  • 1970-01-01
  • 2014-11-07
  • 2011-10-01
  • 1970-01-01
  • 2016-10-02
  • 1970-01-01
  • 2013-11-30
  • 2011-09-10
相关资源
最近更新 更多