簡體   English   中英

Django Admin 中的外鍵和其他字段聚合

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM