Фильтрация записей по дате django
Подскажите, пожалуйста, не могу разобраться, ответа не нашел. Есть 2 модели:
class Datadate(models.Model):
date = models.DateField('Date', unique=True)
class Data(models.Model):
date_id = models.ForeignKey(Datadate, on_delete=models.CASCADE, related_name='dates')
title = models.CharField('Title', max_length=60, default='Empty')
hours = models.FloatField('Hours', default=0)
Мне необходимо выводить записи таблицы Data сгруппированными по дате (например:
01.01.2023 - title1 1час, title2 1час,
02.01.2023 - title3 2часа, title4 3часа)
Через annotate получилось вывести только количество записей за дату
date_set = Datadate.objects.annotate(num_dates=Count('dates'))
{% for e in date_set %}
{{e.num_dates}}
{% endfor %}
но мне нужно выводить title и hours. Подскажите, пожалуйста, как реализовать? Если можно все в одной модели, то переделаю на одну
Ответы (1 шт):
Подход с двумя моделями вполне адекватный, давайте с ним и работать. Плюс разберем пару конфузов.
related_name - в соответствии с документацией - название, которое будет использоваться для возврата от указанного объекта к текущему. По умолчанию джанго сам создает это имя менеджера у связанного объекта, используя шаблон foo_set, где foo - название модели (lowercase).
Таким образом, у вас, если бы не было указано related_name, доступ ко всем связанным Data через Datadate был бы:
last_dd = Datadate.objects.last()
last_dd.data_set.all() # здесь data_set - такой же менеджер, как objects
Тут мы понимаем, что для обратной связи от даты к данным мы задали путающее имя dates - то есть сейчас для доступа к связанным Data через Datadate мы бы использовали
last_dd.dates.all()
Но мы уже вполне можем выводить записи таблицы Data сгруппированными по дате:
date_set = Datadate.objects.prefetch_related('dates').all()
(ссылка на prefetch_related) и в шаблоне
{% for e in date_set %}
{{e.date}} - {% for data in e.dates.all %}{{data.title}} {{data.hours }},{% endfor %}
{% endfor %}
Запятые можно контролировать с помощью forloop.
Рекомендации, не относящиеся к вопросу:
- переименуйте
related_name. Можно вообще его убрать, чтобы пользоватьсяdata_setпо умолчанию, а можно назвать так, чтобы было понятно, что менеджер ведет от даты к данным. (не забудьте про миграции) date_idлучше тоже переименовать - убрать _id. По умолчанию это свойство будет возвращать сам объектDatadate, а не него ID. Если оставить, сам id надо будет получать с помощьюdate_id_id. Подробнее про queryset и как в нем работают поля *_id тоже есть в доках. (снова миграции)
У джанго очень крутой ORM, с большим количеством возможностей и документации. Я постоянно обращаюсь к следующим страницам доков, посмтрите их, там есть много полезного: