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

如何将Django多模型长格式QuerySet转为宽格式并渲染表格?

Django长格式数据转宽格式表格高效实现方案

问题背景

数据库中以长格式存储多模型数据,需要在前端渲染为宽格式表格。现有模型结构如下(已修正原代码中的字段名大小写错误):

class Municipality(models.Model):
    mun_name = models.CharField(max_length=150)
    country = models.CharField(max_length=150)
    
class District(models.Model):
    dis_name = models.CharField(max_length=150)
    municipality = models.ForeignKey(Municipality, on_delete=models.PROTECT)
    
class DistrictStatistics(models.Model):
    district = models.ForeignKey(District, on_delete=models.PROTECT)  # 修正为大写District类名
    measurement = models.ForeignKey(Measurement, on_delete=models.PROTECT)
    value = models.IntegerField()
    
    class Meta:
        unique_together = ["district", "measurement"]  # 修正为小写字段名

class Measurement(models.Model):
    measurement_name = models.CharField(max_length=150, primary_key=True)
    description = models.TextField()

当前查询返回长格式数据,渲染出的表格每行对应一个市政区+测量指标的组合,但需要将测量指标转为列,市政区作为行,缺失值填充为0。

最高效实现方案

核心思路是利用数据库聚合查询直接生成宽格式数据,避免在Python层进行大量数据转换,性能最优。具体步骤如下:

1. 修改视图逻辑,实现数据库层面聚合

通过Django ORM的annotate结合Case/When,将每个测量指标转为市政区的聚合字段:

from django.db.models import Sum, Case, When, IntegerField
from django.shortcuts import render

def measurement_list(request):
    # 获取所有测量指标名称,用于表头和聚合字段
    measurements = Measurement.objects.values_list('measurement_name', flat=True)
    
    # 构建每个测量指标的聚合规则
    annotate_fields = {}
    for meas_name in measurements:
        annotate_fields[meas_name] = Sum(
            Case(
                When(
                    district__districtstatistics__measurement__measurement_name=meas_name,
                    then='district__districtstatistics__value'
                ),
                default=0,
                output_field=IntegerField()
            )
        )
    
    # 查询所有市政区,并聚合每个测量指标的值
    municipalities = Municipality.objects.annotate(**annotate_fields).all()
    
    context = {
        'measurements': measurements,
        'municipalities': municipalities
    }
    return render(request, 'table_template.html', context)

2. 前端模板渲染宽格式表格

在模板中动态生成表头和数据行,通过getattr过滤器获取市政区对象的聚合字段值:

<table>
    <thead>
        <tr>
            <th>Municipality Name</th>
            {% for meas in measurements %}
                <th>{{ meas }}</th>
            {% endfor %}
        </tr>
    </thead>
    <tbody>
        {% for mun in municipalities %}
            <tr>
                <td>{{ mun.mun_name }}</td>
                {% for meas in measurements %}
                    <td>{{ mun|getattr:meas }}</td>
                {% endfor %}
            </tr>
        {% endfor %}
    </tbody>
</table>

方案优势

  • 性能最优:聚合逻辑由数据库完成,仅需2次数据库查询(获取测量指标、聚合市政区数据),避免Python层循环处理大量数据。
  • 扩展性强:新增测量指标时无需修改代码,自动同步到表格中。
  • 数据准确:利用数据库原生聚合函数保证数据计算的准确性,缺失值自动填充为0。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:01:30