#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'
)
Вот текущая ошибка, которую я получаю:
Мой код теперь выглядит довольно беспорядочно, и я все еще получаю вышеуказанную ошибку. Правильно ли я поступаю с этим агрегированием? Если да, то как мне исправить ошибку? Если нет, то каков лучший способ выполнить эту агрегацию динамических списков изменений?
Заранее спасибо.