Djangoで、週間カレンダー

Twitterでシェア FaceBookでシェア はてなブックマークでシェア

Python - Django
2018年11月22日21:14に更新(約21日前)
2018年10月7日16:51に作成(約67日前)

旧ブログ移行記事です。

概要

Djangoで、カレンダーを作るシリーズの1つです。 週間カレンダーを作成していきます。

以下のようなものが作れます。 週間カレンダー

少し地味に見えるかもしれませんが、月間カレンダーに比べると幅をとらないのが特徴です。なので、その分色々な機能を後で付け足していきます(その日のスケジュール表示など)。

scalendar/views.py

週間カレンダー用のMixinクラスを定義します。

class WeekCalendarMixin(BaseCalendarMixin):
    """週間カレンダーの機能を提供するMixin"""

    def get_week_days(self):
        """その週の日を全て返す"""
        month = self.kwargs.get('month')
        year = self.kwargs.get('year')
        day = self.kwargs.get('day')
        if month and year and day:
            date = datetime.date(year=int(year), month=int(month), day=int(day))
        else:
            date = datetime.date.today().replace(day=1)
        for week in self._calendar.monthdatescalendar(date.year, date.month):
            if date in week:  # 週ごとに取り出され、中身は全てdatetime.date型。該当の日が含まれていれば、それが今回表示すべき週です
                return week

    def get_week_calendar(self):
        """週間カレンダー情報の入った辞書を返す"""
        self.setup()
        days = self.get_week_days()
        first = days[0]
        last = days[-1]
        calendar_data = {
            'now': datetime.date.today(),
            'days': days,
            'previous': first - datetime.timedelta(days=7),
            'next': first + datetime.timedelta(days=7),
            'week_names': self.get_week_names(),
            'first': first,
            'last': last,
        }
        return calendar_data

WeekCalendarMixinの説明

一番重要なメソッドはget_week_calendarメソッドで、これが週間カレンダー構築に必要なものが詰まった辞書を返します。 以下は、辞書の各キーと返すものの説明です。

now

現在の日付で、datetime.date型のオブジェクトを返します。これを使うと、その日が今日なら色をつける...なんてことができます。

days

これは、その週の全ての日を返しています。なので、7つのdatetime.dateオブジェクトが返されます。 月をまたいている日付が出ることもありますが、正しく跨いだ月でのdatetime.date型になっています、安心です。

first

一週間の、最初の日です(datetime.date型)

last

一週間の、最後の日です(datetime.date型)

previous

前の週です。週の始まりを示すfirstを基準に、7日引いているだけです。(datetime.date型)

next

次の週です。週の始まりを示すfirstを基準に、7日足しているだけです(datetime.date型)

MonthCalendarMixinに比べると、大分シンプルですね。

sampleapp/urls.py

/weekと、/week/2018/5/5 のようなURLで、週間カレンダーが表示されます。 year、month、dayといった名前は固定です。年と月と日さえわかればその週を取り出せるので、中なか便利です。

    path('week/', views.WeekCalendar.as_view(), name='week'),
    path('week/<int:year>/<int:month>/<int:day>/', views.WeekCalendar.as_view(), name='week'),

sampleapp/views.py

WeekCalendarMixinを継承するだけです。MonthCalendarMixinを使い方は同じですね。

from django.views import generic
from scalendar.views import MonthCalendarMixin, WeekCalendarMixin
...
...

class WeekCalendar(WeekCalendarMixin, generic.TemplateView):
    """週間カレンダーを表示するビュー"""
    template_name = 'sampleapp/week.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['week'] = self.get_week_calendar()
        return context

week.html

週間カレンダーのテンプレートです。month.htmlと、流れは同じです。

{% extends 'sampleapp/base.html' %}
{% block content %}

<a href="{% url 'sampleapp:week' week.previous.year week.previous.month  week.previous.day %}">前週</a>
{{ week.first | date:"Y年m月d日" }}〜{{ week.last | date:"Y年m月d日" }}
<a href="{% url 'sampleapp:week' week.next.year week.next.month  week.next.day %}">次週</a>
<table class="table">
  <thead>
    <tr>
      {% for w in week.week_names %}
        <th>{{ w }}</th>
      {% endfor %}
    </tr>
  </thead>
  <tbody>
      <tr>
        {% for day in week.days %}
          {% if week.now == day %}
            <td class="table-success">
          {% else %}
            <td>
          {% endif %}
          {% if week.first.month != day.month %}
            {{ day | date:"m/d" }}
          {% else %}
            {{ day.day }}
          {% endif %}
          </td>
        {% endfor %}
      </tr>
  </tbody>
</table>
{% endblock %}
Twitterでシェア FaceBookでシェア はてなブックマークでシェア

記事にコメントする