Django 左连接?
我有一些模型,大致是这样的:
class ModelA(models.Model):
field = models.CharField(..)
class ModelB(models.Model):
name = models.CharField(.., unique=True)
modela = models.ForeignKey(ModelA, blank=True, related_name='modelbs')
class Meta:
unique_together = ('name','modela')
我想做一个查询,内容类似于:“获取所有字段名为X的ModelA,并且这些ModelA要么有一个名字为X的ModelB,要么根本没有ModelB。”
到目前为止,我有这个:
ModelA.objects.exclude(field=condition).filter(modelsbs__name=condition)
这个查询会让我得到所有至少有一个ModelB的ModelA(实际上通常只会有一个)——但是如果一个ModelA没有相关的ModelB,它就不会出现在结果里。我希望即使没有ModelB,它也能出现在结果中,像这样obj.modelb = None。
我该怎么做才能实现这个呢?
4 个回答
1
试试这个补丁来处理自定义连接: https://code.djangoproject.com/ticket/7231
1
看起来你遇到了80%的瓶颈。为什么不试试用 .extra(select={'has_x_or_none':'(EXISTS (SELECT ...))'})
来执行一个子查询呢?你可以随意写这个子查询,并且应该能够根据新字段进行筛选。最终生成的SQL语句大概会是这样的:
SELECT *,
((EXISTS (SELECT * FROM other WHERE other.id=primary.id AND other.name='X'))
OR (NOT EXISTS (SELECT * FROM other WHERE other.id=primary.id))) AS has_x_or_none
FROM primary WHERE has_x_or_none=1;
11
用Q来把这两个条件结合起来:
from django.db.models import Q
qs = ModelA.objects.exclude(field=condition)
qs = qs.filter(Q(modelbs__name=condition) | Q(modelbs__isnull=True))
要查看生成的SQL查询:
print qs.query.as_sql()
在类似的查询中,这会生成一个左外连接(LEFT OUTER JOIN),并且条件是(a.val = b 或者 a.id 是空的)。