edche
edche

Reputation: 678

How to list objects of the same date?

I want to list all items in my template, but I want to list items under the same year. For example, under the 2021 title, model objects for that year should be listed. Year titles should come dynamically. How can I do it?

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 %}

To be clear: 2021

Upvotes: 1

Views: 119

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476574

You can work with the {% regroup … by … %} template tag [Django-doc]:

{% regroup press_contents by year as pressitems %}
{% for pressyear in pressitems %}
    <div class="card" style="width: 18rem; margin:15px">
    <div class="card-header">
                {{ pressyear.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 %}

Upvotes: 3

nigel222
nigel222

Reputation: 8192

If you can afford to convert a queryset into a list of objects, then you can use the built-in template filter regroup (I think, I've never used it).

Another approach would be to write a python generator function and pass it in the context, to be iterated over by the template. This avoids issues with resource consumption when the queryset comprises a large number of objects. Something like

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

and

{% for obj in year_grouper %}
    {% if obj.year_changed %}
       ... year header, etc.
    {% endif %}
    ... display obj
{% endfor %}

Upvotes: 1

Related Questions