[FIXED] How Do I Get The Events In Between Start and End Time To Display On My Calendar

Issue

I’m using a tutorial I found online…and it’s mostly working…I’m stuck trying to loop through a list of events and display them each day. If I have an event that starts on June 1st and ends on June 5th, I want to be able to list the event on June 2nd and the events on June 3rd and June 4th. thinking about. Starts June 1st and ends June 5th. I’ve tried several different filters with GTE and LTE, but it doesn’t seem to work.

This is my calendar utility…

class Calendar(HTMLCalendar):
    def __init__(self, year=None, month=None, dropdown=None):
        self.dropdown = dropdown
        self.year = year
        self.month = month
        super(calendar, self).__init__()

    # format day as td
    # Filter events by day
    def formatday(self, day, event):
        events_per_day = events.filter(start_time__day__lte=day, end_time__day__gte=day)
        d = ''
        Events for events_per_day:
            d += f'
  • {event.get_html_url}
  • ' If days != 0: return f"{day}
      {d}
    " returns '' # Format week as tr def formatweek(self, theweek, events): week = '' For d, the day of the week: week += self.formatday(d, event) returns f' {week} ' # format months as a table # Filter events by year and month def formatmonth(self, withyear=True): events = VacationRequest.objects.filter(vacation_calendar=self.dropdown,start_time__year=self.year,start_time__month=self.month).order_by('start_time') cal = f'\n' cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n' cal += f'{self.formatweekheader()}\n' Week of self.monthdays2calendar(self.year, self.month) : cal += f'{self.formatweek(week, event)}\n' cal += f'
    \n' cal += f'

    Vacation schedule for {self.formatmonthname(self.year, self.month, withyear=withyear)}

    \n' Return value

    Here’s my view…

    class VacationRequestCalendarView(generic.ListView):
        Model = VacationRequest
        template_name = 'Vacation request_calendar_view.html'
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            Dropdown = (self.request.GET.get("Dropdown", None))
            d = get_date(self.request.GET.get('month', none))
            cal = Calendar(d.year, d.month, dropdown)
            cal.setfirstweekday(calendar.SUNDAY)
            html_cal = cal.formatmonth(withyear=True)
            Vacation_calendar = VacationCalendar.objects.get(id=self.request.GET.get("dropdown", None))
            Vacation_calendar_requests = VacationRequest.objects.filter(start_time__year = d.year,start_time__month = d.month)
            context['calendar'] = mark_safe(html_cal)
            context['dropdown'] = dropdown
            context['next_month'] = next_month(d)
            context['prev_month'] = prev_month(d)
            context['vacation_calendar_requests'] = Vacation_calendar_requests
            context['vacation_calendar'] = vacation_calendar
            return the context
    
        def get_object (self, queryset=None):
            return get_object_or_404(VacationCalendar, id=self.request.GET.get("Dropdown"))
    
    Default get_date(req_month):
        For req_month:
            year, month = (int(x) of x in req_month.split('-'))
            Return date (date = 1)
        returns datetime.today()
    
    def prev_month(d):
        first = d.replace(day = 1)
        prev_month = first - timedelta(days=1)
        month = 'month=' + str(previous month.year) + '-' + str(previous month.month)
        return month
    
    Default next_month(d):
        days_in_month = calendar.monthrange(d.year, d.month)[1]
        last = d.replace (day = number of days in month)
        next_month = last + timedelta(day=1)
        month = 'month=' + str(next month.year) + '-' + str(next month.month)
        return month
     

    And here is my Django template logic for him…

     {% ifvacation_calendar_requests %}
    
        Requests for {% Vacation_calendar_requests %}
    
          
    {% ifchanged request.start_time|date:"M d, Y" %}

    {{ request.start_time|date:"M d, Y" }}

    {% endifchanged %}
    {% end for ichanged %} {% other than that %}

    No vacation plans

    {% endif %}

    The code above will properly display events that span multiple days on the calendar… this is due to the formatday function. I can see that the events by day are filtered correctly… I am not sure how to do the same when trying to output the events by day using template logic.

    I see that the template loop only finds 2 events…that’s how I do it…but how can I loop by day instead of just the range to find the events? Uka (start time and end time?)

    Add…

    I found an example online how to do what I’m trying to do.. but I don’t know how to incorporate it into the code above… the example I found is…

    from datetime import timedelta, date
    
    Default date range (date 1, date 2):
        for n in range(int ((date2 - date1).days)+1):
            yield date1 + timedelta(n)
    
    start_dt = date(2015, 12, 20)
    end_dt = date (January 11, 2016)
    For date range dt (start_dt, end_dt):
        print(dt.strftime("%Y-%m-%d"))
     

    And it’s from https://www.w3resource.com/python-exercises/date-time-exercise/python-date-time-exercise-50.php

    But I don’t know how to include it…

    Update…

    I got a little closer by updating the Calendar utility to add the following code for the month format.

     for self.monthdays2calendar(self.year, self.month):
        For events:
            # cal += f'{self.formatmonthname(self.year, self.month)}\n'
            cal += f'{self.formatweek(week, event)}\n'
            Return value
     

    I’m almost done… except I’m printing some extra digits from the calendar format… I’m trying to print the month, day and year in the proper format.

    Solution

    I would calculate the duration (number of days), and then use that duration as the number of times to loop. Then to get the date for each day of the duration, I would use a counter variable (enumerator maybe) and add it to the date. For example when the counter is 2, then I would add 2 days to the start date to get the current date in the loop.

    Hopefully this would give you an idea.

    Using your example, add this to your view:

    from datetime import timedelta, date
    
    # Add this function outside the View, just like you did with the other ones
    def daterange(date1, date2):
        for n in range(int ((date2 - date1).days)+1):
            yield date1 + timedelta(n)
    
    def get_context_data(self, **kwargs):
        ## other code here ##
        vacation_calendar_requests = VacationRequest.objects.filter(start_time__year = d.year,start_time__month = d.month)
        
        # this will add a new field, "dates", to each event
        for request in vacation_calendar_requests:
            start_date = request.start_time
            end_date = request.end_time
            start_dt = date(start_date.year,start_date.month,start_date.day) # not sure if this is how you get your event start date
            end_dt = date(end_date.year,end_date.month,end_date.day) # not sure if this is how you get your event end date
            request.dates = [date for date in daterange(start_dt, end_dt)] 
        
        ## rest of code here ##
    

    Then in your template, add this nested loop to show the dates for each event:

    {% for date in request.dates %}
       {{ request.vacation_request_name }}
       {{ date }} /* format the date accordingly */
    {% endfor %}
    

    Answered By – Kachinga

    Answer Checked By – Candace Johnson (Easybugfix Volunteer)

    Leave a Reply

    (*) Required, Your email will not be published