"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

Django2.0+Bootstrap4でカレンダー入力を簡単に実現する「bootstrap_datepicker_plus」を使う

デモ画面をDjangoで作っていて、時々、度忘れして困ることを、自分用を兼ねて、サンプルを書いておきます。

今回はカレンダー入力。

環境は Windows + anaconda です。

f:id:arakan_no_boku:20190320212948j:plain

 

 

文字で入力するとチェックが面倒

 

こちらの記事で日付を1行テキスト入力でやりました。

arakan-pgm-ai.hatenablog.com

これでもいいんですが、問題点がひとつ。

所詮、手入力ですから、サーバー側で日付チェックエラーになる確率が、どうしても高くなります。

なので、カレンダー入力を使う。

これが、まあ定石です。

 

bootstrap_datepicker_plus

 

有難いことに。

Django2.0+Bootstrap4の組合せなら、カレンダー入力をシンプルに実現できる手段があります。

bootstrap_datepicker_plus です。

これを使うには、とりあえずインストールが必要です。

pip install bootstrap_datepicker_plus

 今回は日付のカレンダー入力だけをやります。

他にも色々できるみたいですけど、自分はほぼ使わないので、必要になったら調べればいいかな・・って感じです。

そんときは、こちらを調べます。

github.com

 

settings.py

 

使うためには、設定追加が必要です。

INSTALLED_APPS = [
    ・・・
     'bootstrap_datepicker_plus',

INSTALLED_APPSに上記のように追記です。

 

forms.py

 

1行入力「CharField」にカレンダー入力のWidgetを追加する感じです。

from django import forms
import bootstrap_datepicker_plus as datetimepicker

class DafForm(forms.Form):
     one = forms.CharField(
     label='カレンダー入力',
     required=False,
     disabled=False,
     widget = datetimepicker.DatePickerInput(
               format='%Y/%m/%d',
               attrs={'readonly': 'true','id': 'one'},
               options={
                    'locale': 'ja',
                    'dayViewHeaderFormat': 'YYYY年 MMMM',
                    'ignoreReadonly': True,
                    'allowInputToggle': True}))

これで日本語化もできてます。 

楽ちんです。

 

views.py

 

カレンダー入力を表示して、選択された日付を受け取って、一応日付チェック(ほぼ、エラーになるはずがないのですが)して、入力値を表示する。

それだけの処理です。

from django.http.response import HttpResponse
from django.shortcuts import render, render_to_response
from django.contrib.staticfiles.templatetags.staticfiles import static
from . import forms
from django.template.context_processors import csrf
import datetime
import os

def demo4(request):
    if request.method == 'POST':
        one = request.POST["one"]
        if _is_date_error(one):
            ret = '日付変換エラーが発生しました。(' + one + ')' 
        else:
            ret = one
            
        c = {'ret':ret}        
    else:
        form = forms.DafForm()
        ret = ''
        c = {'form': form,'ret':ret}
        # CFRF対策(必須)
        c.update(csrf(request))
    return render(request,'demo05.html',c)

# サーバー側バリデーション。日付に変換できるかを試している
def _is_date_error(datestring):
    try:
        tdatetime = datetime.datetime.strptime(datestring, '%Y/%m/%d')
        tdate = datetime.date(tdatetime.year, tdatetime.month, tdatetime.day)
        return False
    except:
        return True

特に補足の必要はないくらい、シンプルです。

 

HTML(demo05.html)
{% block content %}
{{ form.media }}
<div class="container bg-light">
    <form action="" method="post">{% csrf_token %}
        <h1>ビルトインフォームサンプル</h1>
        {% if ret %}
        	<div class="form-group row my-4">  
            	<label class="col-lg-3 col-form-label">
            		<h4>入力日付</h4>
            	</label>
       			<div class="col-lg-6">       
	            	<h4>{{ ret }}</h4>
    			</div>
    		</div>        	
        {% else %}
        	{% for key,val in errors.items %}
        		<h2>{{ key }} : {{ val }}</h2>
        	{% endfor %}
        	{% for field in form %}
        	<div class="form-group row my-4">  
            	<label class="col-lg-3 col-form-label">
            		<h4>{{ field.label_tag }}</h4>
            	</label>
       			<div class="col-lg-6">       
	            	{{ field|add_class:"form-control font-weight-bold" }}
    			</div>
    		</div>
			{% endfor %}
		   	<div class="form-group row my-4">	
    			<div class="col-lg-3">       
	        	    <button type="submit" class="btn btn-primary">送信する</button>
    			</div>
        	</div>
         {% endif %}
     </form>
</div>  
{% endblock %}

表示するHTMLテンプレートは、1行テキスト入力の時と同じやり方です。

arakan-pgm-ai.hatenablog.com

 

今回の記事の前提

 

django、bootstrapのインストールや利用設定、および、djangoで入力画面を作る部分は、以下の記事の内容を前提にしています。

arakan-pgm-ai.hatenablog.com

arakan-pgm-ai.hatenablog.com

arakan-pgm-ai.hatenablog.com

 

実行イメージ

 

さて。

runserverで実行します。

 

 

初期表示

 

f:id:arakan_no_boku:20190214221323j:plain

 

実行後の結果表示

 

f:id:arakan_no_boku:20190214221507j:plain

 

こんな感じです。

ではでは。