Skip to main content
 首页 » 编程设计

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

2024年08月19日36lidabo

我有以下工作代码:

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_id 列表的查询集。我想进一步过滤,以便我只获取属于该机构的 100 多个房屋的 area_ids。

我尝试了以下调整:

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 作为数据库后端。

请您参考如下方法:

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

另请注意,您的字段 area_id 和 house_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 .