You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Django Query API实现多表关联的树木品种计数查询?

Django Query API实现公园树木统计方案

核心逻辑对应

你的需求是统计指定公园内按区域分组的树木品种数量,包含现存树木(removed IS NULL)和空置位置,本质是种植位与现存树木的左连接+分组统计。从Park模型出发,用Django Query API可以通过以下方式实现:

前提:模型关联配置

确保你的模型反向关联名称正确(如果没设置related_name,则用默认的_set后缀),示例模型结构参考:

# models.py
class Park(models.Model):
    name = models.CharField(max_length=100)

class Area(models.Model):
    park = models.ForeignKey(Park, related_name="areas", on_delete=models.CASCADE)
    name = models.CharField(max_length=100)

class PlantingSpot(models.Model):
    area = models.ForeignKey(Area, related_name="planting_spots", on_delete=models.CASCADE)
    # 可选:位置编号等字段

class Tree(models.Model):
    planting_spot = models.OneToOneField(PlantingSpot, related_name="tree", on_delete=models.SET_NULL, null=True, blank=True)
    species = models.CharField(max_length=100)
    removed = models.DateTimeField(null=True, blank=True)

实现代码

从指定公园出发,直接生成统计结果:

# views.py
from django.db.models import Count, Case, When, Value, CharField, Q

def park_tree_stats(request, park_id):
    # 生成按区域、品种(含空置)分组的统计数据
    stats = Park.objects.filter(id=park_id).values(
        # 分组字段:区域名称
        area_name="areas__name",
        # 处理空置位置:将空的品种替换为"空置",对应SQL的COALESCE
        species=Case(
            When(areas__planting_spots__tree__species__isnull=True, then=Value("空置")),
            default="areas__planting_spots__tree__species",
            output_field=CharField()
        )
    ).annotate(
        # 统计符合条件的种植位:要么无树(空置),要么树未被移除(现存)
        total=Count(
            "areas__planting_spots",
            filter=Q(areas__planting_spots__tree__removed__isnull=True) | Q(areas__planting_spots__tree__isnull=True)
        )
    ).order_by("area_name", "species")

    # 转换为易读的字典格式(可选)
    result = [
        {
            "区域": item["area_name"],
            "品种": item["species"],
            "数量": item["total"]
        }
        for item in stats
    ]
    return render(request, "stats.html", {"stats": result})

关键细节说明

  • 左连接逻辑:通过areas__planting_spots__tree的嵌套关联,Django会自动生成左连接SQL,结合filter参数确保仅关联未移除的树木,和你原SQL的LEFT JOIN trees t ON ps.id = t.planting_spot_id AND t.removed IS NULL逻辑完全一致。
  • 分组统计:values()指定分组的区域和品种,annotate()用Count统计数量,filter参数筛选出符合要求的种植位。
  • 空置显示:Case/When把无树的种植位品种显示为"空置",对应SQL中的COALESCE(t.species, '空置')。

验证生成的SQL

可以通过打印stats.query查看生成的SQL,会和你手动编写的SQL结构匹配,确保逻辑正确。

内容的提问来源于stack exchange,提问作者afs76

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:12:45