Возвращает набор запросов к спискам, сгруппированным по дате

#python #django

#python #django

Вопрос:

В моей базе данных есть модель транзакций, которая хранит все мои банковские транзакции и отображает их на странице. Все они перечислены, но список очень длинный. Чтобы сократить его, я хочу сгруппировать их по месяцам / годам, чтобы я мог создать на странице сворачиваемый список со свернутыми месяцами, за исключением текущего месяца. Длительный поиск возвращает только функции aggregate и annotate (которые я не до конца понимаю). Самое близкое, что я получил, это:

 >>> data = Transaction.objects.annotate(month=TruncMonth('date')).values('month').annotate(c=Count('id')).values('month', 'c')
>>> data
<QuerySet [{'month': datetime.date(2016, 12, 1), 'c': 74}, {'month': datetime.date(2017, 1, 1), 'c': 109}, {'month': datetime.date(2017, 2, 1), 'c': 70}, {'month': datetime.date(2017, 3, 1), 'c': 92}, {'month': datetime.date(2017, 4, 1), 'c': 79}, {'month': datetime.date(2017, 5, 1), 'c': 79}, {'month': datetime.date(2017, 6, 1), 'c': 83}, {'month': datetime.date(2017, 7, 1), 'c': 99}, {'month': datetime.date(2017, 8, 1), 'c': 98}, {'month': datetime.date(2017, 9, 1), 'c': 112}, {'month': datetime.date(2017, 10, 1), 'c': 87}, {'month': datetime.date(2017, 11, 1), 'c': 82}, {'month': datetime.date(2017, 12, 1), 'c': 86}, {'month': datetime.date(2018, 1, 1), 'c': 113}, {'month': datetime.date(2018, 2, 1), 'c': 98}, {'month': datetime.date(2018, 3, 1), 'c': 121}, {'month': datetime.date(2018, 4, 1), 'c': 111}, {'month': datetime.date(2018, 5, 1), 'c': 107}, {'month': datetime.date(2018, 6, 1), 'c': 91}, {'month': datetime.date(2018, 7, 1), 'c': 97}, '...(remaining elements truncated)...']>
  

Как вы можете видеть, это просто подсчитывает транзакции, которые произошли в том же месяце / году. Я хочу, чтобы на самом деле были перечислены все транзакции.

Вот моя модель транзакции:

 class Transaction(models.Model):
   date = models.DateField(default=datetime.date.today)
   description = models.CharField(max_length=100)
   category = models.CharField(max_length=100)
   amount = models.DecimalField(max_digits=10, decimal_places=2)

   def __str__(self):
       return self.description
  

Комментарии:

1. Скрытые (свернутые) части также отображаются и просто скрыты, или вы создадите новый запрос к базе данных, когда пользователь решит открыть свернутый месяц?

2. Они отображаются и скрыты. Я уже разобрался с этой частью, просто пытаюсь перенести ее на страницу, сгруппированную подобным образом. Не знаю, будет ли ответ просто сгруппировать его в шаблоне

Ответ №1:

Одним из решений является выполнение группировки в представлении.

Вы могли бы выполнить итерацию по своему набору запросов в своем представлении и назначить записи подспискам за год / месяц / что угодно; затем передайте эти подсписки в свой шаблон для рендеринга.

 import collections

data = collections.defaultdict(list)
for t in Transaction.objects.all():
    group = (t.date.year, t.date.month)
    data[group].append(t)
  

В этом фрагменте кода переменной data является dict , которая имеет год-месяц в качестве ключей и списки Transaction (соответствующие этому году и месяцу) в качестве значений.

Таким образом, вы избегаете сложного запроса, если вы все равно собираетесь отображать все записи.

Комментарии:

1. В основном это сработало. Мне просто пришлось преобразовать обратно в обычный dict, чтобы иметь доступ к данным, когда я передал их в шаблон