Django ForeignKey,null = True,内连接和左外连接

时间:2010-02-17 05:32:09

标签: django left-join inner-join

假设我有两个Django模型Person and Company如下: -

class Company(models.Model):
    name = models.CharField()

class Person(models.Model):
    last_name = models.CharField(blank=True)
    first_name = models.CharField()
    company = models.ForeignKey(Company, null=True, blank=True)

某人可能属于也可能不属于公司。

我正在使用MySQL。我希望所有不属于任何公司的人员,即公司无效的人员。

如果我Person.objects.filter(company__isnull=True)我得到的SQL本质上是: -

SELECT * FROM PersonTable LEFT OUTER JOIN AgencyTable ON (PersonTable.company_id = AgencyTable.id) WHERE AgencyTable.id IS NULL

如何实现以下SQL: -

SELECT * FROM PersonTable INNER JOIN AgencyTable ON (PersonTable.company_id = AgencyTable.id) WHERE AgencyTable.id IS NULL

从我从阅读Django Users邮件列表中收集的内容来看,这曾经是QuerySet Refactor之前的行为。

编辑 - 现在我看到了我的问题的亵渎!

我想说的是我只想做

SELECT * FROM PersonTable WHERE PersonTable.company_id IS NULL

3 个答案:

答案 0 :(得分:14)

嗯,这个问题已经过时了,很快补丁就会出现在Django中。但在此期间,答案在http://code.djangoproject.com/ticket/10790

  

解决方法:而不是

     

Person.objects.filter(company=None)

     

使用

     

Person.objects.exclude(company__isnull=False)

答案 1 :(得分:1)

应该如此简单:

Person.objects.filter(company_id__isnull=True)

请注意使用company_id,它是ForeignKey

创建的默认整数字段

修改

对不起,我从0.9.5开始就没有主动使用django。要么我正在考虑1.0之前的行为,要么我正在混淆sqlalchemy和Django ORM。在任何一种情况下,正如评论所述,上述内容似乎无效。

看起来在当前django中获取所需查询的唯一方法是使用.extra查询参数,该参数附带一系列警告。

Person.objects.extra(where=['company_id IS NULL'])

请注意,这可能无法移植到所有数据库,并且可能无法与filter()以及任何可能的问题一起使用。我建议不要在整个代码中使用它,而是将其移动到Person上的类方法,如:

 @classmethod
 def list_unaffiliated_people(cls):
    return cls.objects.extra(where=['company_id IS NULL'])

或者,只需使用正确的ORM查询语法并吸收可能的性能损失(您是否真的对更复杂的查询进行基准测试,看它是否更慢?)

答案 2 :(得分:0)

Django会将NULL视为Python的None对象,所以:

Person.objects.filter(company = None)