Агрегирование строк списка изменений в Django с использованием значений

#python #django #django-models #aggregate

Вопрос:

Я пытаюсь изменить список изменений моей модели, чтобы пользователь мог выбирать различные фильтры, которые будут суммировать определенные поля в модели, группируя их по разным временным рамкам (неделя, месяц, год). Я создал обычай SimpleListFilter , который правильно выполняет агрегацию. Проблема в том, что он использует values метод, который возвращает dict объекты вместо моей модели, вызывая различные ошибки.

Моя модель:

 class UsageReport(models.Model):
    install = models.ForeignKey(
        Installation,
        on_delete=models.CASCADE,
        help_text='The install this report is associated with'
    )
    date = models.DateField(
        null=False,
        blank=False,
        default=None,
        help_text='The day this report's data is compiled for'
    )
    players_count = models.PositiveIntegerField(
        null=False,
        blank=False,
        default=0,
        help_text='The number of new players created'
    )
    captures_count = models.PositiveIntegerField(
        null=False,
        blank=False,
        default=0,
        help_text='The number of new captures created'
    )
    created_at = models.DateTimeField(auto_now_add=True, null=True)
 

Мой пользовательский фильтр списка:

 class DateGroupFilter(SimpleListFilter):
    title = 'Group By'
    parameter_name = 'group_by_date'

    def lookups(self, request, model_admin):
        return (
            ('week', 'Week'),
            ('month', 'Month'),
            ('year', 'Year')
        )

    def queryset(self, request, queryset):
        if self.value() == 'week':
            return queryset.annotate(week=ExtractWeek('date')).values('install', 'week').annotate(
                sum_players=Sum('players_count')).annotate(sum_captures=Sum('captures_count'))
        if self.value() == 'month':
            return queryset.annotate(month=ExtractMonth('date')).values('install', 'month').annotate(
                sum_players=Sum('players_count')).annotate(sum_captures=Sum('captures_count'))
        if self.value() == 'year':
            return queryset.annotate(year=ExtractYear('date')).values('install', 'year').annotate(
                sum_players=Sum('players_count')).annotate(sum_captures=Sum('captures_count'))
 

Так как каждый параметр фильтра возвращает несколько разные поля (неделя, месяц, год) Я попытался закодировать обходной путь, который переопределяет get_list_display метод в моем ModelAdmin классе, а также добавляет метод для каждого из различных имен полей (которые просто извлекают значение из возвращаемого dict ), но это все равно выдает ошибку, потому dict что у него нет необходимого _meta атрибута.

My ModelAdmin:

 @admin.register(UsageReport)
class AdminUsageReport(admin.ModelAdmin):
    search_fields = ('install__name', 'install__id', 'date')
    ordering = ['-install__name', '-date']
    list_display_links = None
    list_select_related = []
    list_filter = (
        DateGroupFilter,
    )

    def week(self, obj):
        return obj['week']

    def month(self, obj):
        return obj['month']

    def year(self, obj):
        return obj['year']

    def sum_players(self, obj):
        return obj['sum_players']

    def sum_captures(self, obj):
        return obj['sum_players']

    def get_list_display(self, request):
        if request.GET.get('group_by_date') == 'week':
            return (
                'install',
                'week',
                'sum_players',
                'sum_captures'
            )
        elif request.GET.get('group_by_date') == 'month':
            return (
                'install',
                'month',
                'sum_players',
                'sum_captures'
            )
        elif request.GET.get('group_by_date') == 'year':
            return (
                'install',
                'year',
                'sum_players',
                'sum_captures'
            )
        else:
            return (
                'install',
                'date',
                'players_count',
                'captures_count'
            )
 

Вот текущая ошибка, которую я получаю:
Текущее сообщение об ошибке

Мой код теперь выглядит довольно беспорядочно, и я все еще получаю вышеуказанную ошибку. Правильно ли я поступаю с этим агрегированием? Если да, то как мне исправить ошибку? Если нет, то каков лучший способ выполнить эту агрегацию динамических списков изменений?

Заранее спасибо.