Python 在admin-Django中使用sum和display数据进行多注释
我对Django和Python都是新手。目前,我正在尝试Django管理员 我有三种Django应用程序模型,分别是Python 在admin-Django中使用sum和display数据进行多注释,python,django,django-admin,django-annotate,Python,Django,Django Admin,Django Annotate,我对Django和Python都是新手。目前,我正在尝试Django管理员 我有三种Django应用程序模型,分别是GoodsItem、SoldGoodsItem和FinishedGoodsItem。models.py是: from django.db import models class GoodsItem(models.Model): name = models.CharField(max_length=255) size = models.DecimalField(m
GoodsItem
、SoldGoodsItem
和FinishedGoodsItem
。models.py是:
from django.db import models
class GoodsItem(models.Model):
name = models.CharField(max_length=255)
size = models.DecimalField(max_digits=4, decimal_places=2)
INCHES = 'IN'
NUMBER = 'NUM'
GOODS_ITEM_SIZE_UNITS = (
(INCHES, 'Inches'),
(NUMBER, '#'),
)
size_unit = models.CharField(
max_length=4,
choices=GOODS_ITEM_SIZE_UNITS,
default=INCHES,
)
def __str__(self):
if(self.size_unit == self.NUMBER):
return "%s #%s" % (self.name, (self.size).normalize())
else:
return "%s %s\"" % (self.name, (self.size).normalize())
class FinishedGoodsItem(models.Model):
date = models.DateField()
goods_item = models.ForeignKey(GoodsItem, on_delete=models.CASCADE, related_name="finished_name")
weight = models.DecimalField(max_digits=6, decimal_places=3)
def __str__(self):
return str(self.goods_item)
class SoldGoodsItem(models.Model):
goods_item = models.ForeignKey(GoodsItem, on_delete=models.CASCADE, related_name="sold_name")
date = models.DateField()
weight = models.DecimalField(max_digits=6, decimal_places=3)
def __str__(self):
return str(self.goods_item)
这里是admin.py:
from django.contrib import admin
from django.db.models import Sum
from .models import GoodsItem, FinishedGoodsItem, SoldGoodsItem
@admin.register(SoldGoodsItem)
@admin.register(FinishedGoodsItem)
class FinishedGoodsItemAdmin(admin.ModelAdmin):
fields = ('date', 'goods_item', 'weight')
list_display = ('date', 'goods_item', 'weight')
@admin.register(GoodsItem)
class GoodsItemAdmin(admin.ModelAdmin):
list_display = ('__str__', 'finished_good', 'sold_good', 'stock_available')
def get_queryset(self, request):
qs = super(GoodsItemAdmin, self).get_queryset(request)
qs = qs.annotate(
finished_good=Sum('finished_name__weight'),
sold_good=Sum('sold_name__weight'),
stock_available=Sum('finished_name__weight') - Sum('sold_name__weight'),
)
return qs
def finished_good(self, obj):
return obj.finished_good
def sold_good(self, obj):
return obj.sold_good
def stock_available(self, obj):
return obj.stock_available
在每个
GoodsItem
的stock\u available
中,我想显示FinishedGoodsItem
的所有条目与SoldGoodsItem
的所有条目之间的差异。目前,我得到的所有三个带注释字段的值都不正确,它们是已完成商品
,已售出商品
和库存可用
。我找不到原因。在Django调试工具栏中,提示正在执行重复的查询。这是一个已知问题,当我们尝试组合多个聚合时会发生,如中所述
作为这个特殊问题的解决方法,我们可以使用子查询表达式。这是我在GoodsItemAdmin
的get\u queryset
方法中使用子查询表达式更新的admin.py
from django.contrib import admin
from django.db.models import Subquery, Sum, OuterRef
from .models import GoodsItem, FinishedGoodsItem, SoldGoodsItem
@admin.register(SoldGoodsItem)
class SoldGoodsItemAdmin(admin.ModelAdmin):
fields = ('date', 'goods_item', 'weight')
list_display = ('date', 'goods_item', 'weight')
@admin.register(FinishedGoodsItem)
class FinishedGoodsItemAdmin(admin.ModelAdmin):
fields = ('date', 'goods_item', 'weight')
list_display = ('date', 'goods_item', 'weight')
@admin.register(GoodsItem)
class GoodsItemAdmin(admin.ModelAdmin):
list_display = ('__str__', 'finished_good', 'sold_good', 'stock_available')
def get_queryset(self, request):
qs = super(GoodsItemAdmin, self).get_queryset(request)
qs = qs.annotate(
finished_good = Subquery(FinishedGoodsItem.objects.filter(goods_item=OuterRef('pk'))\
.values('goods_item_id').annotate(sum=Sum('weight')).values('sum')[:1]),
sold_good = Subquery(SoldGoodsItem.objects.filter(goods_item=OuterRef('pk'))\
.values('goods_item_id').annotate(sum=Sum('weight')).values('sum')[:1])
)
return qs
def finished_good(self, obj):
return obj.finished_good
def sold_good(self, obj):
return obj.sold_good
def stock_available(self, obj):
finished_good = 0 if self.finished_good(obj) is None else self.finished_good(obj)
sold_good = 0 if self.sold_good(obj) is None else self.sold_good(obj)
return '-' if (finished_good == 0 and sold_good == 0) else finished_good - sold_good
希望有人觉得这很有用。我发现这很有用,下面是使用此方法简单计算的方法(具体地说,计算与每个ThisTable行相关的相关行的相关行数):
count=Subquery(models.ThisTable.objects.filter(id=OuterRef('id')).annotate(count=count('related\u outerrelated')).values('count')
这对我不起作用,子查询只返回一个权重,不做任何求和。