目次
Datepickerとは?
Datepickerはカレンダー選択による日時入力インターフェースです。
日時入力フィールドにフォーカスを与えるとカレンダーがポップアップ表示され、カレンダーで年月日時間を選択することで指定の値を入力することが出来ます。
django-bootstrap-datepicker-plus
ここではDjango用Datepickerのライブラリである「django-bootstrap-datepicker-plus」をご紹介します。
条件
- Django 2.1.3
- Python 3.7.0
DjangoでのDatepickerの使い方
PyCharmでdjango-bootstrap-datepicker-plusを使用するチュートリアルの手順をご紹介します。
以下のサイトを参考にしています。
https://django-bootstrap-datepicker-plus.readthedocs.io/en/latest/Walkthrough.html
プロジェクトのチェックアウト
バージョン管理からのチェックアウト > Gitで以下のURLを指定しプロジェクトをクローンします。
https://github.com/monim67/django-polls
以下のように「django-polls」プロジェクトがクローンされます。
必要パッケージのインストール
- django-bootstrap4
- django-bootstrap-datepicker-plus
メニューのファイル > 設定 > プロジェクト:django-polls > プロジェクト・インタープリターを選択します。
右上「最新バージョン」横の+ボタンを押します。
使用可能なパッケージ画面が開くので検索入力欄に「django-bootstrap4」を入力します。
「django-bootstrap4」が選択された状態でパッケージのインストールボタンを押してインストールします。
同様に「django-bootstrap-datepicker-plus」もインストールします。
使用可能なパッケージ画面を閉じると、パッケージ一覧に「django-bootstrap4」「django-bootstrap-datepicker-plus」が追加されていることがわかります。
OKボタンを押して設定画面を閉じます。
INSTALLED_APPSへの追記
mysite/settings.pyのINSTALLED_APPSに以下の2行を追記します。
"bootstrap4", "bootstrap_datepicker_plus",
CreateViewの追加
polls/views.pyにCreateViewを追記します。
# FIle: polls/views.py from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.views import generic from bootstrap_datepicker_plus import DateTimePickerInput from .models import Choice, Question class CreateView(generic.edit.CreateView): model = Question fields = ['question_text', 'pub_date'] def get_form(self): form = super().get_form() form.fields['pub_date'].widget = DateTimePickerInput() return form # 他のクラスは変更なし
テンプレートファイルの追加
polls/templates/polls/question_form.htmlを追加します。
<!-- File: polls/templates/polls/question_form.html --> {% load bootstrap4 %} {% bootstrap_css %} {% bootstrap_javascript jquery='full' %} {{ form.media }} <form method="post">{% csrf_token %} {% bootstrap_form form %} <input type="submit" value="Save"> </form>
モデルにget_absolute_urlを追加
polls/models.pyのQuestionモデルにget_absolute_urlメソッドを追加します。
# FIle: polls/models.py import datetime from django.db import models from django.urls import reverse from django.utils import timezone class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') def __str__(self): return self.question_text def was_published_recently(self): return self.pub_date >= timezone.now() - datetime.timedelta(days=1) def get_absolute_url(self): return reverse('polls:detail', kwargs={'pk': self.pk})
URLパターンの追加
polls/urls.pyのURLパターンにcreateを追加します。
# FIle: polls/urls.py from django.urls import path from . import views app_name = 'polls' urlpatterns = [ path('', views.IndexView.as_view(), name='index'), path('create', views.CreateView.as_view(), name='create'), path('<int:pk>/', views.DetailView.as_view(), name='detail'), path('<int:pk>/results/', views.ResultsView.as_view(), name='results'), path('<int:question_id>/vote/', views.vote, name='vote'), ]
実行
Ctrl + Alt + Rを押してPyCharmのmanage.pyコンソールを開きます。
「runserver」を入力してEnterを押します。
ブラウザで以下のURLを開きます。
http://localhost:8000/polls/create
「Date published」の入力欄または右側のカレンダーアイコンをクリックするとカレンダーがポップアップ表示します。
カレンダーを閉じると選択した日時が入力された状態になります。
以上で完了です。
日時のフォーマット指定
以下のように、パラメータでformatを指定することで日時の表示を変えることが出来ます。
class CreateView(generic.edit.CreateView): model = Question fields = ['question_text', 'pub_date'] def get_form(self): form = super().get_form() form.fields['pub_date'].widget = DateTimePickerInput(format='%Y-%m-%d') return form
NGケース(解決方法あり)
原因は不明ですが、「format=’%Y/%m/%d’」とすると、日時のフォーマットチェックに必ず引っかかってしまうようです。
原因
Djangoの日時チェックで使用される「DATETIME_INPUT_FORMATS」に「’%Y/%m/%d’」が無いのが原因です。
DATETIME_INPUT_FORMATS = [ '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59' '%Y-%m-%d %H:%M:%S.%f', # '2006-10-25 14:30:59.000200' '%Y-%m-%d %H:%M', # '2006-10-25 14:30' '%Y-%m-%d', # '2006-10-25' '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59' '%m/%d/%Y %H:%M:%S.%f', # '10/25/2006 14:30:59.000200' '%m/%d/%Y %H:%M', # '10/25/2006 14:30' '%m/%d/%Y', # '10/25/2006' '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59' '%m/%d/%y %H:%M:%S.%f', # '10/25/06 14:30:59.000200' '%m/%d/%y %H:%M', # '10/25/06 14:30' '%m/%d/%y', # '10/25/06' ]
対応
settings.pyに以下を記述することで、日時チェックを通すことが出来ます。
USE_L10N = False # DATETIME_INPUT_FORMATSに変更を加えるため、Falseに設定 from django.conf.global_settings import DATETIME_INPUT_FORMATS DATETIME_INPUT_FORMATS += ('%Y/%m/%d',)
settings.pyを以下のように記述しても、日時チェックが通るようです。
LANGUAGE_CODE = 'ja-jp' TIME_ZONE = 'Asia/Tokyo' USE_I18N = True USE_L10N = True USE_TZ = False from django.conf.global_settings import DATETIME_INPUT_FORMATS DATETIME_INPUT_FORMATS += ('%Y/%m/%d',)
カスタムフォームで使用する
カスタムフォームで「django-bootstrap-datepicker-plus」を使用する方法をご紹介します。
カスタムフォーム追加
polls/forms.pyを追加します。
# File: forms.py from bootstrap_datepicker_plus import DatePickerInput from django import forms class ToDoForm(forms.Form): todo = forms.CharField( widget=forms.TextInput(attrs={"class": "form-control"}) ) date = forms.DateField( widget=DatePickerInput(format='%m/%d/%Y') )
viewsの編集
polls/viewsのCreatViewにget_context_dataを追加してToDoFormをcontextに渡すようにします。
from .forms import ToDoForm class CreateView(generic.edit.CreateView): model = Question fields = ['question_text', 'pub_date'] def get_form(self): form = super().get_form() form.fields['pub_date'].widget = DateTimePickerInput() return form def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) form = ToDoForm() context['todo_form'] = form return context
テンプレートの編集
polls/templates/polls/question_form.htmlに{{ todo_form }}を追記します。
<!-- File: polls/templates/polls/question_form.html --> {% load bootstrap4 %} {% bootstrap_css %} {% bootstrap_javascript jquery='full' %} {{ form.media }} <form method="post">{% csrf_token %} {% bootstrap_form form %} <input type="submit" value="Save"> </form> {{ todo_form }}
サーバー実行
「runserver」を実行し、ブラウザで以下のURLを開きます。
http://localhost:8000/polls/create
追加したToDoフォームが追加されていることがわかります。
フォームの設定例
フォームでオプションを指定することにより様々な設定を行うことが出来ます。
以下は、開始日時と終了日時で日時にの大小に齟齬が出ないようにした一例です。
「.start_of(‘term’)および.end_of(‘term’)」でペアを指定しています。
また、初期表示や表示フォーマット、最小/最大日時の設定なども行っています。
class SampleForm(forms.Form): start_date = forms.DateField( label='開始日時', widget=datetimepicker.DateTimePickerInput( format='%Y/%m/%d %H:%M:%S', options={ 'locale': 'ja', 'dayViewHeaderFormat': 'YYYY年 MMMM', 'ignoreReadonly': True, 'allowInputToggle': True, 'minDate': '2018/10/22', # 最小日時(データ取得開始日) 'defaultDate': '2018/10/22', # 初期表示 } ).start_of('term'), ) end_date = forms.DateField( label='終了日時', initial=dt.now().strftime('%Y/%m/%d %H:%M:%S'), # 初期値 widget=datetimepicker.DateTimePickerInput( format='%Y/%m/%d %H:%M:%S', options={ 'locale': 'ja', 'dayViewHeaderFormat': 'YYYY年 MMMM', 'ignoreReadonly': True, 'allowInputToggle': True, 'maxDate': (dt.now() + timedelta(days = 1)).strftime('%Y/%m/%d %H:%M:%S'), # 最大日時(翌日) } ).end_of('term'), )
詳細は以下を参照してください。
http://eonasdan.github.io/bootstrap-datetimepicker/Options/
参考
django-bootstrap-datepicker-plus documentation
https://django-bootstrap-datepicker-plus.readthedocs.io/en/latest/index.html