Как составить список объектов с одинаковой датой?

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

views.py

def press_list(request):
    press_contents = PressContent.objects.all().order_by('-date')
    context = {
        'press_contents': press_contents
    }
    return render(request, "press_list.html", context)

models.py

class PressContent(models.Model):
    label = models.CharField(max_length=500)
    url = models.URLField(max_length=500)
    date = models.DateTimeField(blank=True, null=True)
    

press_list.html

{% for press in press_contents %}
        <div class="card" style="width: 18rem; margin:15px">
            <div class="card-header">
                {{ press.date.year }}
            </div>
            <ul class="list-group list-group-flush">
                <li class="list-group-item"><a href="{{ press.url }}">{{ press.label }}</a></li>
                # Other objects from this year should come here.
            </ul>
        </div>
{% endfor %}

Для ясности: 2021

  • пока 1
  • bj 2 2020
  • obj 3
  • .
  • bj 4 ... ...

Вы можете работать с тегом шаблона {% regroup … by … %} [Django-doc]:

{% regroup press_contents by year as press %}
{% for pressyear in press_contents %}
    <div class="card" style="width: 18rem; margin:15px">
    <div class="card-header">
                {{ press.date.grouper }}
            </div>
            <ul class="list-group list-group-flush">
                {% for press in pressyear.list %}
                    <li class="list-group-item"><a href="{{ press.url }}">{{ press.label }}</a></li>
                # Other objects from this year should come here.
                {% endfor %}
            </ul>
        </div>
{% endfor %}

Если вы можете позволить себе преобразовать queryset в список объектов, то вы можете использовать встроенный фильтр шаблона regroup (кажется, я никогда не использовал его).

Другим подходом может быть написание функции-генератора на языке python и передача ей контекста, который будет итерироваться шаблоном. Это позволяет избежать проблем с потреблением ресурсов, когда набор запросов состоит из большого количества объектов. Что-то вроде

def year_grouper():
    qs = PressContent.objects.all().order_by('-date')
    last_object_year = 1000000000
    for obj in qs:
        obj.year_changed = ( obj.date.year != last_object_year )
        yield obj
        last_object_year = obj.date.year

и

{% for obj in year_grouper %}
    {% if obj.year_changed %}
       ... year header, etc.
    {% endif %}
    ... display obj
{% endfor %}
Вернуться на верх