title: How to use HTMLCalendar
body: <p>I'm using Django, and I'm using the HTMLCalendar module to print a calendar on a page.
  Currently, the code below works fine, but when the date between 'from date' and 'to date' is more than 2days, I want to express it in one line instead of adding an event to each date belonging to the period.
  No matter how hard I searched, I couldn't find any posts with similar difficulties, and I haven't been able to solve them on my own for several days. Help!</p>
  <p>[models.py]</p>
  <pre><code>class Leave(models.Model):
      title = models.CharField(max_length=50, blank=True, null=True)
      from_date = models.DateField(blank=True, null=True)
      end_date = models.DateField(blank=True, null=True)
      memo = models.TextField(blank=True, null=True)
      user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
      is_deleted = models.BooleanField(default=False)
      create_date = models.DateTimeField(auto_now_add=True)
      update_date = models.DateTimeField(auto_now=True)
  
      @property
      def get_html_url(self):
          url = reverse('leave:leave_edit', args=(self.id,))
          return f'&lt;div class=&quot;event-title&quot; colspan=&quot;{self.end_date - self.from_date}&quot;&gt;&lt;a href=&quot;{url}&quot; style=&quot;color:black;&quot;&gt; {self.title} &lt;/a&gt;&lt;/div&gt;'
  </code></pre>
  <p>[forms.py]</p>
  <pre><code>class LeaveForm(ModelForm):
    class Meta:
      model = Leave
      # datetime-local is a HTML5 input type, format to make date time show on fields
      widgets = {
        'from_date': DateInput(attrs={'type': 'datetime', 'class': 'datepicker', 'autocomplete': 'off'}, format='%Y-%m-%d'),
        'end_date': DateInput(attrs={'type': 'datetime', 'class': 'datepicker', 'autocomplete': 'off'}, format='%Y-%m-%d'),
        'user': Select(attrs={&quot;disabled&quot;: 'disabled'}),
      }
      fields = ['title', 'from_date', 'end_date', 'memo', 'user']
  
    def __init__(self, request, *args, **kwargs):
      super(LeaveForm, self).__init__(*args, **kwargs)
      # input_formats to parse HTML5 datetime-local input to datetime field
      self.fields['from_date'].input_formats = ('%Y-%m-%d',)
      self.fields['end_date'].input_formats = ('%Y-%m-%d',)
      self.fields['user'].empty_label = request.user.username
  </code></pre>
  <p>[utils.py]</p>
  <pre><code>class Calendar(HTMLCalendar):
  def __init__(self, year=None, month=None, user=None):
      self.year = year
      self.month = month
      self.user = user
      super(Calendar, self).__init__()
  
  # formats a day as a td
  # filter events by day
  def formatday(self, day, events, next_visit):
      events_per_day = events.filter(user=self.user).annotate(end_date_month=ExtractMonth('end_date'))\
          .filter(Q(from_date__day=day, end_date__isnull=True) |
                  Q(from_date__day__lte=day, end_date__day__gte=day) |
                  (Q(from_date__day__lte=day, from_date__year=self.year, from_date__month=self.month) &amp;
                   ~Q(from_date__month=F('end_date_month'))) |
                  (Q(end_date__day__gte=day, end_date__year=self.year, end_date__month=self.month) &amp;
                   ~Q(from_date__month=F('end_date_month'))))
  
      next_visit_per_day = next_visit.filter(next_visit__day=day, next_visit__year=self.year, next_visit__month=self.month, assignment__curr_crc=self.user.first_name)
  
      d = ''
      for event in events_per_day:
          d += f'{event.get_html_url}'
  
      for next_visit in next_visit_per_day:
          d += f'{next_visit.get_html_url}'
  
      if day != 0:
          return f&quot;&lt;td&gt;&lt;span class='date'&gt;{day}&lt;/span&gt;&lt;ul&gt; {d} &lt;/ul&gt;&lt;/td&gt;&quot;
      return '&lt;td&gt;&lt;/td&gt;'
  
  # formats a week as a tr
  def formatweek(self, theweek, events, next_visit):
      week = ''
      for d, weekday in theweek:
          week += self.formatday(d, events, next_visit)
      return f'&lt;tr&gt; {week} &lt;/tr&gt;'
  
  # formats a month as a table
  # filter events by year and month
  def formatmonth(self, withyear=True):
      events = Leave.objects.filter(is_deleted=False)\
                            .filter(Q(from_date__year=self.year, from_date__month=self.month) |
                                    Q(end_date__year=self.year, end_date__month=self.month))
  
      next_visit = Feedback.objects.filter(assignment__is_deleted=0, next_visit__isnull=False)
  
      cal = f'&lt;table border=&quot;0&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;calendar&quot;&gt;\n'
      cal += f'{self.formatmonthname(self.year, self.month, withyear=withyear)}\n'
      cal += f'{self.formatweekheader()}\n'
      for week in self.monthdays2calendar(self.year, self.month):
          cal += f'{self.formatweek(week, events, next_visit)}\n'
      return cal
  </code></pre>
  <p>[views.py]</p>
  <pre><code>class CalendarView(generic.ListView):
  model = Leave
  template_name = 'pages/leave/leave.html'
  
      def get_context_data(self, **kwargs):
          context = super().get_context_data(**kwargs)
  
          # use today's date for the calendar
          d = get_date(self.request.GET.get('month', None))
          context['prev_month'] = prev_month(d)
          context['next_month'] = next_month(d)
          first_name = self.request.user
  
          # Instantiate our calendar class with today's year and date
          cal = Calendar(d.year, d.month, first_name)
         cal.setfirstweekday(6)
  
          # Call the formatmonth method, which returns our calendar as a table
          html_cal = cal.formatmonth(withyear=True)
          context['calendar'] = mark_safe(html_cal)
          context['leave'] = Leave.objects.filter(is_deleted=0)
  
          return context
  
  def get_date(req_day):
       if req_day:
          year, month = (int(x) for x in req_day.split('-'))
          return datetime.date(year, month, day=1)
      return datetime.datetime.today()
  
  def prev_month(d):
      first = d.replace(day=1)
      prev_month = first - datetime.timedelta(days=1)
      month = 'month=' + str(prev_month.year) + '-' + str(prev_month.month)
      return month
  
  def next_month(d):
      days_in_month = calendar.monthrange(d.year, d.month)[1]
      last = d.replace(day=days_in_month)
      next_month = last + datetime.timedelta(days=1)
      month = 'month=' + str(next_month.year) + '-' + str(next_month.month)
      return month
  
  def leave(request, leave_id=None):
      instance = Leave()
      if leave_id:
          instance = get_object_or_404(Leave, pk=leave_id)
      else:
          instance = Leave()
      instance
      form = LeaveForm(request, request.POST or None, instance=instance)
      if request.POST and form.is_valid():
          form = form.save(commit=False)
          form.user = request.user
         form.save()
          return HttpResponseRedirect(reverse('leave:calendar'))
      return render(request, 'pages/leave/leave_add.html', {'form': form})
  
  
  @login_required()
  def leave_delete(request, leave_id):
      leave = Leave.objects.get(pk=leave_id)
      leave.is_deleted = True
      leave.save()
      return HttpResponseRedirect(f'/leave/calendar/')
  </code></pre>