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

如何基于分类在HTML表格展示Django Stock模型数据

Django按分类分组展示库存项解决方案

需求说明

Stock模型中每个库存项归属一个分类,需提取唯一分类,将对应分类的库存项展示在独立HTML表格中,并在表格上方显示分类名称作为标题。

现有模型(无需修改)

# models.py
class Stock(models.Model):
    user = models.ForeignKey(User, on_delete = models.SET_NULL, null = True)
    part_No = models.CharField(max_length=100, null=True)
    item_name = models.CharField(max_length=100, null=True)
    category = models.CharField(max_length=100, null=True)
    unit = models.CharField(max_length=50, null=True)
    balance_bd = models.IntegerField(default='0', null = True)
    received = models.IntegerField(default='0', null = True)
    issued = models.IntegerField(default='0', null=True)
    unit_price = models.DecimalField(max_digits=20,  decimal_places=2, null=True)
    obsolete = models.BooleanField(default=False, null=True)

修改后的视图函数

# views.py
from itertools import groupby
from django.db.models import F
from django.shortcuts import render

def stock(request):
    # 按分类排序,确保分组逻辑生效
    stocks = Stock.objects.order_by('category').annotate(
        # 计算模板中需要的衍生字段
        total_bal=F('balance_bd') + F('received'),
        tally_card_bal=F('total_bal') - F('issued'),
        total_price=F('tally_card_bal') * F('unit_price')
    )
    
    # 按分类分组,生成{分类名称: 库存项列表}的字典
    grouped_stocks = {}
    for category, items in groupby(stocks, key=lambda x: x.category):
        grouped_stocks[category] = list(items)
    
    # 计算所有库存项的总价总和
    sum_total_price = sum(
        stock.total_price for stock in stocks 
        if stock.total_price is not None
    )
    
    context = {
        'grouped_stocks': grouped_stocks,
        'sumTotalPrice': sum_total_price
    }
    return render(request, 'base/stock.html', context)

修改后的HTML模板

<!-- base/stock.html -->
<div class="container mt-4">
    <!-- 遍历所有分类分组 -->
    {% for category, stocks in grouped_stocks.items %}
        {% if category %}
            <!-- 分类标题 -->
            <h3 class="mt-5">{{ category }}</h3>
            
            <!-- 分类对应的库存表格 -->
            <div class="table-responsive m-b-40">
                <table class="table table-borderless table-data3">
                    <thead>
                        <tr class="bg-primary">
                            <th>序号</th>
                            <th>零件编号</th>
                            <th>描述</th>
                            <th>分类</th>
                            <th>单位</th>
                            <th>期初余额</th>
                            <th>入库量</th>
                            <th>总库存</th>
                            <th>出库量</th>
                            <th>卡账余额</th>
                            <th>单价</th>
                            <th>总价</th>
                            <th>操作</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for stock in stocks %}
                            {% if stock.obsolete %}
                            <tr>
                                <td>{{ forloop.counter }}</td>
                                <td class="text-success"><i>{{ stock.part_No }}</i></td>
                                <td class="text-success"><i>{{ stock.item_name }}(已淘汰)</i></td>
                                <td class="text-success"><i>{{ stock.category }}</i></td>
                                <td class="text-success"><i>{{ stock.unit }}</i></td>
                                <td class="text-success"><i>{{ stock.balance_bd }}</i></td>
                                <td class="text-success"><i>{{ stock.received }}</i></td>
                                <td class="text-success"><i>{{ stock.total_bal }}</i></td>
                                <td class="text-success"><i>{{ stock.issued }}</i></td>
                                <td class="text-success"><i>{{ stock.tally_card_bal }}</i></td>
                                <td class="text-success"><i>${{ stock.unit_price }}</i></td>
                                <td class="text-success"><i>${{ stock.total_price }}</i></td>
                                <td>
                                    <div class="table-data-feature">
                                        <a href="{% url 'update-item' stock.id %}">
                                            <button class="item" data-toggle="tooltip" data-placement="top" title="更新">
                                                <i class="zmdi zmdi-edit"></i>
                                            </button>
                                        </a>
                                        <button class="item" data-toggle="tooltip" data-placement="top" title="删除">
                                            <i class="zmdi zmdi-delete"></i>
                                        </button>
                                    </div>
                                </td>
                            </tr>
                            {% else %}
                            <tr>
                                <td>{{ forloop.counter }}</td>
                                <td>{{ stock.part_No }}</td>
                                <td>{{ stock.item_name }}</td>
                                <td>{{ stock.category }}</td>
                                <td>{{ stock.unit }}</td>
                                <td>{{ stock.balance_bd }}</td>
                                <td>{{ stock.received }}</td>
                                <td>{{ stock.total_bal }}</td>
                                <td>{{ stock.issued }}</td>
                                <td>{{ stock.tally_card_bal }}</td>
                                <td>${{ stock.unit_price }}</td>
                                <td>${{ stock.total_price }}</td>
                                <td>
                                    <div class="table-data-feature">
                                        <a href="{% url 'update-item' stock.id %}">
                                            <button class="item" data-toggle="tooltip" data-placement="top" title="更新">
                                                <i class="zmdi zmdi-edit"></i>
                                            </button>
                                        </a>
                                        <button class="item" data-toggle="tooltip" data-placement="top" title="删除">
                                            <i class="zmdi zmdi-delete"></i>
                                        </button>
                                    </div>
                                </td>
                            </tr>
                            {% endif %}
                        {% empty %}
                            <tr>
                                <td colspan="13" class="text-center">该分类下无库存项</td>
                            </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
        {% endif %}
    {% empty %}
        <p class="text-center">库存中无任何项</p>
    {% endfor %}

    <!-- 总价格汇总 -->
    <div class="text-right mt-4">
        <p style="font-weight: bold; font-size: 1.2rem;">总价格: ${{ sumTotalPrice }}</p>
    </div>
</div>

关键改动说明

  1. 视图层:

    • 对查询集按category排序,保证groupby能正确分组
    • 通过annotate计算模板所需的衍生字段,避免在模板中做复杂计算
    • 将库存项按分类分组后传入模板,简化模板遍历逻辑
  2. 模板层:

    • 遍历分组后的字典,每个分类生成独立标题和表格
    • 保留原有库存项的样式逻辑(已淘汰项的斜体和绿色文本)
    • 处理空分类、分类无库存、整体无库存的边界情况
    • 总价格汇总移至所有表格下方,更符合展示逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 20:50:29