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

Django Admin中Sum注解计算库存可用量异常问题求助

Hey there! Let's work through this Django Admin annotation problem together—since you're new to Django and Python, I'll keep this straightforward so you can follow along easily.

First, let's address why your current annotate approach is giving incorrect values: when you directly use Sum with related models, Django joins the tables behind the scenes, which can create duplicate rows in the queryset. This duplication makes the sum calculations inflate because the same parent GoodsItem gets counted multiple times for each related FinishedGoodsItem or SoldGoodsItem.

Fixing the Calculation with Subqueries

The solution is to use subqueries to calculate the total finished and sold quantities for each GoodsItem individually, avoiding duplicate row issues. Here's how to implement this in your admin.py:

First, let's assume your models have the correct foreign key relationships (adjust if your field names differ):

# models.py
from django.db import models

class GoodsItem(models.Model):
    name = models.CharField(max_length=100)
    # Add any other fields you have for GoodsItem

class FinishedGoodsItem(models.Model):
    goods_item = models.ForeignKey(GoodsItem, on_delete=models.CASCADE, related_name="finished_entries")
    quantity = models.IntegerField()
    # Other fields for finished goods

class SoldGoodsItem(models.Model):
    goods_item = models.ForeignKey(GoodsItem, on_delete=models.CASCADE, related_name="sold_entries")
    quantity = models.IntegerField()
    # Other fields for sold goods

Now update your admin.py to use subqueries for accurate sums:

# admin.py
from django.contrib import admin
from django.db.models import Sum, Subquery, OuterRef
from .models import GoodsItem, FinishedGoodsItem, SoldGoodsItem

class GoodsItemAdmin(admin.ModelAdmin):
    # Display these fields in the admin list view
    list_display = ('name', 'total_finished', 'total_sold', 'stock_available')

    def get_queryset(self, request):
        # Subquery to calculate total finished quantity per GoodsItem
        finished_total_subquery = FinishedGoodsItem.objects.filter(
            goods_item=OuterRef('pk')
        ).values('goods_item').annotate(
            total=Sum('quantity')
        ).values('total')

        # Subquery to calculate total sold quantity per GoodsItem
        sold_total_subquery = SoldGoodsItem.objects.filter(
            goods_item=OuterRef('pk')
        ).values('goods_item').annotate(
            total=Sum('quantity')
        ).values('total')

        # Attach the subquery results to the GoodsItem queryset
        queryset = super().get_queryset(request).annotate(
            _total_finished=Subquery(finished_total_subquery, output_field=models.IntegerField()),
            _total_sold=Subquery(sold_total_subquery, output_field=models.IntegerField())
        )
        return queryset

    # Helper method to display total finished (handle None values)
    def total_finished(self, obj):
        return obj._total_finished or 0
    total_finished.short_description = 'Total Finished'

    # Helper method to display total sold (handle None values)
    def total_sold(self, obj):
        return obj._total_sold or 0
    total_sold.short_description = 'Total Sold'

    # Calculate available stock
    def stock_available(self, obj):
        return self.total_finished(obj) - self.total_sold(obj)
    stock_available.short_description = 'Available Stock'

# Register your models with the custom admin classes
admin.site.register(GoodsItem, GoodsItemAdmin)
admin.site.register(FinishedGoodsItem)
admin.site.register(SoldGoodsItem)

Why This Works

  • Subqueries calculate the sum for each GoodsItem independently, so there's no duplication from table joins.
  • We handle None values (for items with no finished or sold entries) using or 0 to avoid errors in calculations.
  • The get_queryset method ensures these calculations are done efficiently at the database level, not in Python.

Just adjust the related_name values and field names to match your actual model setup, and this should give you the correct stock_available values in the Django Admin.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:28:43