在Django中关联两个模型并按产品名称分组求和(含金额计算)
解决方案
你需要通过Django的聚合函数和F()表达式实现关联模型分组、数量求和及总金额计算,以下是具体实现步骤:
修改视图代码
from django.db.models import Sum, F from django.shortcuts import render def stockPrice(request): # 关联产品详情,按产品分组统计库存并计算各类总金额 stock = InventorySummary.objects.select_related('product_name')\ .values( 'product_name__id', 'product_name__product_name', 'product_name__purchase_price', 'product_name__dealer_price', 'product_name__retail_price' )\ .annotate(total_quantity=Sum('quantity'))\ .annotate( total_purchase=Sum('quantity') * F('product_name__purchase_price'), total_dealer=Sum('quantity') * F('product_name__dealer_price'), total_retail=Sum('quantity') * F('product_name__retail_price') ) return render(request, 'inventory_price.html', {'stock': stock})
代码说明
select_related('product_name'):提前关联ProductDetails模型,避免多次查询数据库的N+1问题values():指定需要返回的产品核心字段,通过双下划线__关联外键模型的属性annotate(total_quantity=Sum('quantity')):按产品分组后统计该产品的总库存数量- 第二个
annotate:用F()表达式将求和后的库存数量与对应价格字段相乘,直接在数据库层面计算出不同定价下的总金额
模板渲染示例(inventory_price.html)
<table> <thead> <tr> <th>产品名称</th> <th>总库存数量</th> <th>采购总价</th> <th>经销商总价</th> <th>零售总价</th> </tr> </thead> <tbody> {% for item in stock %} <tr> <td>{{ item.product_name__product_name }}</td> <td>{{ item.total_quantity }}</td> <td>{{ item.total_purchase|floatformat:2 }}</td> <td>{{ item.total_dealer|floatformat:2 }}</td> <td>{{ item.total_retail|floatformat:2 }}</td> </tr> {% endfor %} </tbody> </table>
可选命名优化建议
你的InventorySummary模型中外键字段命名为product_name易造成混淆(实际关联的是整个产品对象而非名称),建议修改为product,更符合Django规范:
class InventorySummary(models.Model): id = models.AutoField(primary_key=True) date = models.DateField(default=date.today) product = models.ForeignKey(ProductDetails, on_delete=models.CASCADE, related_name='inventory') quantity = models.IntegerField() def __str__(self): return str(self.product)
修改后视图中的关联字段需对应调整,比如select_related('product')、values('product__product_name')等,可提升代码可读性。
内容的提问来源于stack exchange,提问作者Shanzedul
相关产品推荐
相关产品推荐

