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

Django模型关联查询:按月份统计作物收获面积并过滤结果

解决方案

模型补全说明

你的Crop模型定义中缺少is_active字段,但Plotting的外键关联里用到了limit_choices_to={"is_active": True}过滤条件,建议给Crop模型添加该字段,否则这个过滤规则会失效:

class Crop(models.Model):
    name = models.CharField(max_length=100, unique=True)
    description = models.TextField(null=True, blank=True)
    is_active = models.BooleanField(default=True)  # 添加此字段

1. 数据库查询实现

使用Django ORM的聚合函数和条件判断,按作物分组统计各月份收获面积总和,同时支持日期范围过滤:

from django.db.models import Sum, Case, When, DecimalField
from datetime import date

def get_crop_harvest_stats(start_date=None, end_date=None):
    # 初始化查询集,过滤有效作物和非空收获日期
    queryset = Plotting.objects.filter(
        crop__is_active=True,
        harvesting_date__isnull=False
    )

    # 应用日期范围过滤
    if start_date:
        queryset = queryset.filter(harvesting_date__gte=start_date)
    if end_date:
        queryset = queryset.filter(harvesting_date__lte=end_date)

    # 按作物分组,统计1-5月的收获面积
    crop_stats = queryset.values('crop__name').annotate(
        jan=Sum(Case(
            When(harvesting_date__month=1, then='acre'),
            output_field=DecimalField(),
            default=0
        )),
        feb=Sum(Case(
            When(harvesting_date__month=2, then='acre'),
            output_field=DecimalField(),
            default=0
        )),
        mar=Sum(Case(
            When(harvesting_date__month=3, then='acre'),
            output_field=DecimalField(),
            default=0
        )),
        apr=Sum(Case(
            When(harvesting_date__month=4, then='acre'),
            output_field=DecimalField(),
            default=0
        )),
        may=Sum(Case(
            When(harvesting_date__month=5, then='acre'),
            output_field=DecimalField(),
            default=0
        ))
    ).filter(
        # 排除所有月份收获面积均为0的作物
        jan__gt=0 | feb__gt=0 | mar__gt=0 | apr__gt=0 | may__gt=0
    ).order_by('crop__name')

    return crop_stats

2. 格式化输出为指定表格

将查询结果转换成你需要的表格格式:

def print_harvest_table(stats):
    # 打印表头
    print(f"CROP NAME | JAN | FEB | MAR | APR | MAY")
    # 打印分隔线增强可读性
    print("----------|-----|-----|-----|-----|-----")
    for stat in stats:
        # 格式化每行内容,保证对齐
        print(f"{stat['crop__name']:<10} | {stat['jan']:>3} | {stat['feb']:>3} | {stat['mar']:>3} | {stat['apr']:>3} | {stat['may']:>3}")

使用示例

# 统计2024年1-5月的收获数据
start = date(2024, 1, 1)
end = date(2024, 5, 31)
stats = get_crop_harvest_stats(start, end)
print_harvest_table(stats)

关键逻辑说明

  • 用Case/When实现条件聚合,每个月份单独计算收获面积总和
  • 通过values('crop__name')按作物名称分组统计
  • 最后的filter规则排除了所有月份收获面积都为0的作物
  • 日期范围过滤通过harvesting_date__gte和harvesting_date__lte实现,可灵活指定统计时间段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 01:30:47