python - 如何在 django 中获取内部连接的表别名
问题描述
我使用 django 2.1、python 3.6 和 SQL Server 2012 作为后端。我有以下型号:
class ModelA(models.Model):
name = models.CharField(...)
value = models.PositiveIntegerField(...)
class ModelB(models.Model):
name = models.CharField(...)
values = models.ManyToManyField(ModelA, through='ModelC')
class ModelC(models.Model):
model_a = models.ForeignKey(ModelA, ...)
model_b = models.ForeignKey(ModelB, ...)
info_a = models.CharField(...)
info_b = models.CharField(...)
如何实现以下 SQL 查询:
SELECT t1.model_a_id AS a_id, t3.value AS a_value
FROM ModelB AS t0
INNER JOIN ModelC t1 ON t1.model_b_id = t0.id
INNER JOIN ModelC t2 ON t2.model_b_id = t0.id
INNER JOIN ModelA t3 ON t3.id = t2.model_a_id
INNER JOIN ModelC t4 ON t4.model_b_id = t0.id
WHERE t1.model_a_id in (1,2) AND t2.model_a_id in (8,9,10,11) AND t4.model_a_id in (21,22)
到目前为止我所拥有的:
ModelB.objects.filter(values__in=[1,2]).filter(values__in=[8,9,10,11]).filter(values__in=[21,22])
这会产生正确的过滤查询集。但是我怎样才能得到正确的字段呢?
我尝试使用annotate
功能,但失败了。使用文档中描述的 django 会Subquery
产生数据库错误,因为 SQL Server 不支持该SELECT
部分中的子查询。
有什么建议吗?谢谢!
解决方案
我解决了它而没有退回到原始 sql。我结合使用了 django 的FilteredRealtion对象,annotate
如下所示:
from django.db.models import Q, F, FilteredRelation
qs = ModelB.objects.filter(values__in=[21,22])
qs = qs.filter(values__in=[1,2])
qs = qs.filter(values__in=[8,9,10,11])
qs = qs.annotate(_a_id=FilteredRelation('modelc', condition=Q(values__in=[8,9,10,11])),
_a_value=FilteredRelation('modelc', condition=Q(values__in=[1,2])))
qs = qs.annotate(a_id=F('_a_id__model_a'), a_value=F('_a_value__model_a__value'))
qs = qs.values('a_id', 'a_value')