DDiran
DDiran

Reputation: 573

Django | Displaying events grouped by month in custom format?

I have the following models:

class Event(Page)
    # my fields
    start_date = models.DateField()
    end_date = models.DateField()

class EventsIndex(Page):
    # my fields

    def get_events(self):
        events = Event.objects.all().sort_by("start_date")
        return events

In my EventsIndex template I have 4 tabs which show the current month, the next month, the month after next and then a final tab called "Later" which should display the individual Events grouped by month:

enter image description here

I'm trying to figure out the logic for which to get these events to display. The individual month tabs should only display the events, whereas the "Later" tab should display a heading of the month of the events and then the events themselves. Initially I thought about creating a function for each tab, so something like:

def current_month_events(self):
    current_month, current_year = datetime.now().month, datetime.now().year
    events = Event.objects.filter(start_date__year=current_year, 
                  start_date__month=current_month).order_by("start_date")
    return events

# Repeat for all required tabs

However this seems to go against the DRY principle. Is there a more pythonic way to handle this logic?

Upvotes: 1

Views: 240

Answers (1)

Withnail
Withnail

Reputation: 3178

I've always been quite annoyed about the lack of support for this type of thing in Django.

Unless you're doing aggregation then it's not terribly well supported.

The most pythonic / Djangorrific way I can find to do it is in the template, using groupby there. (This seems to me to go against the concept of not putting business logic in templates, but there you are.)

In your case, you'd do something like this in the views.py file:

from datetime import date, timedelta
today = date.today()
four_months_time  = today + timedelta(months=4)
events = Event.objects.filter(start_date__gte=today, start_date__lte= 
                  four_months_time).order_by("start_date")`

and in the templates (assuming you pass back events as the variable):

{% regroup events by start_date.month as events_list %}
<ul>
{% for event in events_list %}
    <li>{{ event.grouper }}
    <ul>
        {% for event in event.list %} 
          <li>{{event}}</li>
        {% endfor %}
    </ul>
    </li>
{% endfor %}
</ul>

This is untested, but should send you on the right direction!

Upvotes: 1

Related Questions