1

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?

DDiran
  • 533
  • 1
  • 6
  • 23

1 Answers1

1

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!

Withnail
  • 3,128
  • 2
  • 30
  • 47
  • Nailed it, thanks @Withnail! I had to make a few alterations, such as using relativedelta instead of time delta but it all works flawlessly :) – DDiran Nov 23 '17 at 07:06