[Answered ]-Categorize posts by months and years in Django

1👍

The only thing missing is a .order_by() [Django-doc] (yes, I know that is strange), this will force a GROUP BY statement:

data['news_years'] = (
    News.objects.annotate(year=ExtractYear('nw_publish'))
    .values('year')
    .annotate(total_entries=Count('year'))
    .order_by()
)

as for using months, it might be better to truncate than extract, since then you still have a date object:

from django.db.models.functions import TruncMonth

data['news_years'] = (
    News.objects.values(month=TruncMonth('nw_publish'))
    .annotate(total_entries=Count('month'))
    .order_by()
)

Showing a list of the posts after the click (how to get this list?)

You can make a path with the year and month with:

path(
    'posts/<int:year>/<int:month>/', SomeListView.as_view(), name='posts-by-month'
),

then in the template you link to this with:

{% for news_year in news_years %}
    <a href="{% url 'posts-by-month' news_year.month.year news_year.month.year %}">{{ news_year.month }} ({{ news_year.total_entries }})</a>
{% endfor %}

in the SomeListView, you can then filter with:

class SomeListView(ListView):
    model = News

    def get_queryset(self, *args, **kwargs):
        return (
            super()
            .get_queryset(*args, **kwargs)
            .filter(
                nw_publish__year=self.kwargs['year'],
                nw_publish__month=self.kwargs['month'],
            )
        )

Leave a comment