[英]Aggregation by Foreign Key and other field in Django Admin
我在 Django 工作,並且在我的管理站點中正確顯示某些內容時遇到問題。 這些是模型
class IndexSetSize(models.Model):
""" A time series of sizes for each index set """
index_set = models.ForeignKey(IndexSet, on_delete=models.CASCADE)
byte_size = models.BigIntegerField()
timestamp = models.DateTimeField()
class IndexSet(models.Model):
title = models.CharField(max_length=4096)
# ... some other stuff that isn't really important
def __str__(self):
return f"{self.title}"
它顯示了我需要的所有適當數據,但是,我想顯示 IndexSetSize 的總和,按 index_set 鍵分組並按時間戳分組(對於給定的時間戳,IndexSet 可以多次出現,所以我想將所有字節大小相加)。 目前只顯示每條記錄。 此外,我希望 total_size 字段是可排序的
當前管理員 model 看起來像:
class IndexSetSizeAdmin(admin.ModelAdmin):
""" View-only admin for index set sizes """
fields = ["index_set", "total_size", "byte_size", "timestamp"]
list_display = ["index_set", "total_size", "timestamp"]
search_fields = ["index_set"]
list_filter = ["index_set__title"]
def total_size(self, obj):
""" Returns human readable size """
if obj.total_size:
return humanize.naturalsize(obj.total_size)
return "-"
total_size.admin_order_field = 'total_size'
def get_queryset(self, request):
queryset = super().get_queryset(request).select_related()
queryset = queryset.annotate(
total_size=Sum('byte_size', filter=Q(index_set__in_graylog=True)))
return queryset
似乎在 Django 中進行分組的正確方法是使用.values(),盡管如果我在 get_queryset 中使用它,則會拋出一個錯誤,說Cannot call select_related() after.values() or.values_list()
。 如果有一種“正確”的值/注釋/聚合方法可以與 get_queryset 一起正常工作,我無法在文檔中找到。 這是一個非常簡單的 sum/group by query 我正在嘗試做的事情,但我不確定“Django 方式”是什么來完成它。
謝謝
我認為您不能返回完整的index_set
中的get_queryset
,因為您不能 select 所有列,但按 sql 中的單個列分組
SELECT *, SUM(index_size) FROM indexsetsize GROUP BY index_set // doesn't work
您可以在total_size
方法中執行額外的查詢來獲取聚合值。 但是,這將對返回的每一行執行查詢並減慢頁面加載速度。
def total_size(self, obj):
""" Returns human readable size """
return humanize.naturalsize(sum(IndexSetSize.objects.filter(
index_set=obj.index_set).values_list(
'byte_size', flat=True)))
total_size.admin_order_field = 'total_size'
最好在IndexSetAdmin
中執行此注釋,因為index_set
已經通過反向外鍵分組。 這意味着您可以在get_queryset
中執行注釋。 我還將在related_name
的外鍵上IndexSetSize
,以便您可以使用該名稱從IndexSet
訪問 realted IndexSetSize
對象。
class IndexSetSize(models.Model):
index_set = models.ForeignKey(IndexSet, on_delete=models.CASCADE, related_name='index_set_sizes')
...
class IndexSetAdmin(admin.ModelAdmin):
...
def total_size(self, obj):
""" Returns human readable size """
if obj.total_size:
return humanize.naturalsize(obj.total_size)
return "-"
def get_queryset(self, request):
queryset = super().get_queryset(request).prefetch_related('index_set_sizes').annotate(
total_size=Sum('index_set_sizes__byte_size')).order_by('total_size')
return queryset
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.