list only objects in choosen year

I have a list of years with events.
Now I want to list only events of a choosen year.

views.py

def get_years_with_events(request):
queryset = Event.objects.all().order_by('-date')
years = []
for item in queryset:
    year = item.date.year
    if not year in years:
        years.append(year)
context = {
    "year_list": years
}
return render(request, "events/year_list.html", context)

def events_list_view(request):
queryset = Event.objects.all().order_by('-date')
context = {
    "object_list": queryset
}
return render(request, "events/events_list.html", context)

{% extends 'base.html' %}

{% block content %}

year_list.html
{% include ‘events/events_navbar.html’ %}

Liste Jahre mit Veranstaltungen


{% if year_list %}
{% for year in year_list %}

{{ year }}


{% endfor %}
{% else %}

Es sind noch keine Veranstaltungen erfasst.


{% endif %}
{% endblock %}

How can I filter for a year? Somehow I need to pass the year from year_list.html to the events_list_view as a filter or to get_years_with_events to filter the queryset and return year_list and queryset.

Can you please help me?

I don’t think I can give you the exact code, but with the assumption all events have a date:

Get the value of the ‘year’ you want as a string (eg 2020), cast that string as a datetime type (startdate = datetime.strptime('2020', '%Y'), add one year to stratdate (enddate = startdate + timedelta(years=1)).

You don’t need any more date information than the year, in this case print(startdate) outputs 2020-01-01 00:00:00.

Then create a filter where your event date is >= startdate and < enddate.

Hope that isn’t too abstract for you.

You could annotate your queryset of Events with the extracted year. The issue here is timezones. If you store your datetimes in UTC, then convert them to the requesting user’s timezone, then you may run into issues around timestamps near the new year.

from django.db.models.functions import ExtractYear

tzinfo = None # Or however else you want to set the timezone. If you don't, it'll just use the timezone that the date was stored in.

# Extract the year off the date and put it into a new field on event.
all_events = Event.objects.annotate(
    year=ExtractYear('date', tzinfo=tzinfo)
)

# Fetch a list of all distinct year values for the events.
# This is a good candidate for caching.
years = list(all_events.values_list('year', flat=True).distinct())

# Filter down to the events in the selected year or show all events.
filtered_events = all_events.filter(year=selected_year) if selected_year else all_events

Thank you for the help. I solved it.
<a class="dropdown-item" href="{% url 'events-for-year-list' year %}">{{ year }}</a>

`path('<int:year>/', events_for_year_list_view, name='events-for-year-list'),`