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

che*_*art 9 django inner-join left-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)
Run Code Online (Sandbox Code Playgroud)

一个人可能属于也可能不属于公司.

我正在使用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

Jam*_*inn 14

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

解决方法:而不是

Person.objects.filter(company=None)

使用

Person.objects.exclude(company__isnull=False)


Cra*_*ast 1

它应该像这样简单:

Person.objects.filter(company_id__isnull=True)
Run Code Online (Sandbox Code Playgroud)

请注意,它的使用company_id是由ForeignKey创建的默认整数字段

编辑

抱歉,从 0.9.5 开始我就没有积极使用过 django。要么我正在考虑 1.0 之前的行为,要么我混淆了 sqlalchemy 和 Django ORM。无论哪种情况,正如评论所述,上述内容似乎都不起作用。

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

Person.objects.extra(where=['company_id IS NULL'])
Run Code Online (Sandbox Code Playgroud)

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

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

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