基于相关模型计数的Django过滤

时间:2017-09-20 10:28:06

标签: python django python-3.x django-models

我有以下工作代码:

houses_of_agency = House.objects.filter(agency_id=90)
area_list = AreaHouse.objects.filter(house__in=houses_of_agency).values('area')
area_ids = Area.objects.filter(area_id__in=area_list).values_list('area_id', flat=True)

返回带有area_ids列表的查询集。我想进一步过滤,以便我只获得area_ids,其中有超过100个房屋属于该机构。

我尝试了以下调整:

houses_of_agency = House.objects.filter(agency_id=90)
area_list = AreaHouse.objects.filter(house__in=houses_of_agency).annotate(num_houses=Count('house_id')).filter(num_houses__gte=100).values('area')
area_ids = Area.objects.filter(area_id__in=area_list).values_list('area_id', flat=True)

但它返回一个空的查询集。

我的模型(简化)如下所示:

class House(TimeStampedModel):
    house_pk = models.IntegerField()
    agency = models.ForeignKey(Agency, on_delete=models.CASCADE)


class AreaHouse(TimeStampedModel):
    area = models.ForeignKey(Area, on_delete=models.CASCADE)
    house = models.ForeignKey(House, on_delete=models.CASCADE)


class Area(TimeStampedModel):
    area_id = models.IntegerField(primary_key=True)
    parent = models.ForeignKey('self', null=True)
    name = models.CharField(null=True, max_length=30)

编辑:我使用MySQL作为数据库后端。

1 个答案:

答案 0 :(得分:2)

您只使用一个下划线查询agency_id。我在下面更正了您的疑问。此外,在django中,使用pk代替id更常见,但行为是相同的。此外,由于您可以将所有内容合并为一个查询,因此不需要三个单独的查询。

另请注意,您的字段area_idhouse_pk是不必要的,django会自动创建可通过modelname__pk访问的主要字段字段。

# note how i inlined your first query in the .filter() call
area_list = AreaHouse.objects \
            .filter(house__agency__pk=90) \
            .annotate(num_houses=Count('house')) \  # <- 'house'
            .filter(num_houses__gte=100) \
            .values('area')

# note the double underscore
area_ids = Area.objects.filter(area__in=area_list)\
                       .values_list('area__pk', flat=True)

如果您不需要中间结果,您可以进一步简化此操作。这里是两个查询组合:

area_ids = AreaHouse.objects \
            .filter(house__agency__pk=90) \
            .annotate(num_houses=Count('house')) \
            .filter(num_houses__gte=100) \
            .values_list('area__pk', flat=True)

最后,您似乎在模型中手动定义了多对多关系(通过AreaHouse)。有更好的方法,请阅读django docs

相关问题