我对Django(Python也是)很陌生,并且通过实践来学习它。
我正在玩Django管理站点。我创建了两个模型并在admin中成功注册。 list_display
中给出的字段可以很好地显示数据。
我想要一个admin中的另一个表,它通过一些逻辑处理来显示来自两个表的数据。
要根据前两个模型数据获取另一个表,我可以使用此question中提到的方法创建一个新模型。
现在的问题是,如何从其他模型表中获取数据以及如何返回,以便可以在admin中的表中显示。
这是我的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 self.goods_item
admin中的第三个表应显示如下数据:
===============================
GoodsItem | Stock Available
===============================
此处GoodsItem是GoodsItem模型的字符串表示形式,可用库存应计算为:
FinishedGoodsItem中特定GoodsItem的重量总和,直到最后一个条目(即最后进入日期) - SoldGoodsItem中特定GoodsItem的重量总和,直到最后一个条目(即最后进入日期)
我将实现逻辑,如果某种个性告诉我如何查询数据并通过模型中的不同方法返回。如果有任何疑问,请随时提出。
答案 0 :(得分:1)
据我所知,每个GoodsItem
对象需要一行。您可以将“库存可用”列直接添加到GoodsItem
管理员,而无需创建单独的模型,正如Daniel Roseman所说。
示例代码(可能不是100%正确,但您明白了):
class GoodsItem(models.Model):
# ...
@property
def stock_available(self):
stock_finished = self.finished_name.aggregate(Sum('weight'))['weight__sum']
stock_sold = self.sold_name.aggregate(Sum('weight'))[
'weight__sum']
return stock_finished - stock_sold
class GoodsItemAdmin(admin.ModelAdmin):
# ...
list_display = ('name', 'size', 'size_unit', 'stock_available')
请参阅Django docs on aggregation。请记住,这将对列表中显示的每个项目执行两次额外查询。
编辑: 下面提出的解决方案不起作用,因为Django错误包含聚合和多个表here,如一条评论。请改用使用子查询的this answer。
如果先前的解决方案由于许多查询而太慢,则另一个选项是:
class GoodsItemAdmin(admin.ModelAdmin):
list_display = ('name', 'size', 'size_unit', 'stock_available')
def get_queryset(self, request):
qs = super(GoodsItemAdmin, self).get_queryset(request)
qs = qs.annotate(stock_available=Sum('finished_name__weight') - Sum('sold_name__weight'))
return qs
请注意,最后一个选项仅将功能添加到管理员,但这可能就足够了。