
目次
はじめに
ユーザに日付を入力してもらうインターフェースとしてカレンダーを使いたいというケースは多いと思います。
HTML5 であれば <input type="date"> としておいて描画はブラウザにまかせるのが手っ取り早いかもしれません。HTML5 に限定できない場合は、 "datepicker" 等をキーワードにして探せば複数の JavaScript ライブラリを見つけることが可能だと思います。
一方で、Django の特徴の1つである管理画面作成機能を使った事がある方ならば、管理画面では日付フィールドを含むモデルの追加 / 編集の際にカレンダーを使えることにお気づきかと思います。例えば以下のような感じです。
カレンダーのアイコンをクリックすることによって、カレンダーから日付を入力する事が可能です。
このカレンダーは AdminDateWidget を利用することで実現できます。
そこで、この記事では UI で AdminDateWidget を利用してカレンダー入力を実現するための手順についてまとめました。
必要な手続き
AdminDateWidget でカレンダー入力を行うためには、下記手続きが必要です。
- DateField のウィジェットとして AdminDateWidget を指定する。
- テンプレートのヘッダ内でフォームの media 属性を表示する。
- 2 で不足する Admin 画面のスタイルシート、JavaScript ファイルをヘッダ内に追加する。
AdminDateWidget を指定する
Model を使わない場合
まずは Model を定義せずに、純粋に Form だけを定義する場合を考えてみます。
date_field という日付フィールドのあるフォーム (DateForm) を作成してみます。
from django import forms from django.contrib.admin.widgets import AdminDateWidget class DateForm(forms.Form): date_field = forms.DateField(widget=AdminDateWidget())
フィールドを定義する際に widget 引数で AdminDateWidgets() を割り当てます。
Model を使う場合
次に Model が定義されていて、対応するフォームを表示するケースも考えてみます。
下記のモデルが定義されているとします。
from django.db import models class DateModel(models.Model): date_field = models.DateField()
このモデルに対するフォームを定義する場合には、ModelForm を使うことになると思います。
from django import forms from django.contrib.admin.widgets import AdminDateWidget from .models import DateModel class DateForm(forms.ModelForm): class Meta: model = DateModel fields = ('date_field',) widgets = { 'date_field': AdminDateWidget(), }
class Meta の中で、widgets 属性で 'date_field' のウィジェットを定義しています。
media 属性を描画する
ここでは、実験用として下記のような簡単なビューを用意します。
from django.shortcuts import render from .forms import DateForm def index(request): context = { 'form': DateForm() } return render(request, 'use_admin_widgets/index.html', context)
コンテキスト変数 'form' で DateForm を指定、テンプレートとして index.html を指定しています。
Django ではフォームの media 属性にフォームが依存する css や JavaScript のリストのリストが格納されていますので、テンプレートのヘッダフィールド内でこれを描画します。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Title</title> {{ form.media }} </head> <body> {{ form }} </body> </html>
実際に描画すると、{{ form.media }} の箇所は、下記で置き換えられます。
<script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.js"></script> <script type="text/javascript" src="/static/admin/js/jquery.init.js"></script> <script type="text/javascript" src="/static/admin/js/calendar.js"></script> <script type="text/javascript" src="/static/admin/js/admin/DateTimeShortcuts.js"></script>
この状態ではまだカレンダーは表示されません。
足りないスタイルシートと JavaScript を追加する
先の処置で不足するスタイルシート等を追加したテンプレートは下記のようになります。
{% load static %}<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- for admin widgets --> <link rel="stylesheet" type="text/css" href="{% static 'admin/css/base.css' %}"/> <link rel="stylesheet" type="text/css" href="{% static 'admin/css/forms.css' %}"/> <script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script> {{ form.media }} <script type="text/javascript" src="{% static 'admin/js/core.js' %}"></script> <script type="text/javascript" src="{% static 'admin/js/admin/RelatedObjectLookups.js' %}"></script> <!-- end for admin widgets --> </head> <body> {{ form }} </body> </html>
追加するタグで使用する URL で {% static %} タグを使うために、最初に {% load static %} を記述しておきます。
ヘッダ内に追加する必要のあるタグは、<!-- for admin widgets --> から <!-- end for admin widgets --> に書かれた部分です。
これで下記のように表示されます。
カレンダー部分をクリックすると、下記のようなカレンダーが表示されて入力が可能になります。
以上で、Admin 画面で使用されているカレンダーウィジェットを使用した日付入力を利用できます。
JavaScript逆引きレシピ 第2版 (PROGRAMMER’S RECiPE)