SSブログ

1.10 Bootstrap 4.0+Django-bootstrap-datepicker-plusの利用(DJango 2.2.7) [Django]

今までDjango管理画面のCSSやカレンダーを利用していたが、
見栄えをBootstrap 4.0 に変更するために、
新たにPycharmProjectsd4 をこしらえました。
DBも、SQLite から MySQL 8.0.18に変更。


1.今回のポイント
(1) 日付入力(カレンダー)があるため、datepicker_plus を使いします。
(2) BootstrapのCDNは利用しません。
 パフォーマンスとか考慮するならCDNの方が良いようですが、
 仕事の本番環境を考慮し、ローカルからアクセスするようにしました。
 A. 本番環境がWebアクセス出来ない環境の場合でも耐えられるよう
 B. 何かしらの事由でCDNサイトが利用出来なくなっても耐えられるよう
 C. 社内システムのためそんなにアクセスが爆発的ではないため、
  さほどパフォーマンス考慮が不要なため

  ちなみにダウンロードして配置しているのは以下です。
  bootstrap-4.3.1-dist
  bootstrap-datepicker-1.9.0-dist
  moment.js
  popper.js
  tempusdominus-bootstrap-4
  fontawesome-free-5.11.2-desktop(今回のには関係ない)
  fontawesome-free-5.11.2-web(今回のには関係ない)

  以下フォルダに無造作に配置
  C:\PycharmProjects4\Recruitment\applicantctl\static\applicantctl

WS000029.JPG


2.作業

(1) django-bootstrap-datepicker-plusのインストール
  venv環境にて下記コマンドを実行
  pip install django-bootstrap-datepicker-plus

WS000031.JPG

(2) settings.pyの変更
  'bootstrap_datepicker_plus',を追加(11行目)

# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'accounts.apps.AccountsConfig',
    'applicantctl',
    'bootstrap_datepicker_plus',
    'mytest',
]




(3) Baseテンプレートファイルの変更
  Bootstrap用のURLをbase.htmlへ設定。
  CDNは使わないので、
  {% load bootstrap4 %},{% bootstrap_css %},{% bootstrap_javascript jquery='full' %}
  は、きっと利用出来ないのでベタ書き。(8~11行目、48~49行目)

  Base.html
{% load static %}
<!doctype html>
<html lang="ja">
 <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap CSS -->
	<link href="{% static 'applicantctl/bootstrap-4.3.1-dist/css/bootstrap.min.css' %}" rel="stylesheet">
    <!-- Bootstrap CSS Fotter-->
    <link href="{% static 'applicantctl/bootstrap-4.3.1-dist/sticky-footer-navbar.css' %}" rel="stylesheet">
    <title>applicantctl-django</title>
	{% block head_meta %}{% endblock %}
</head>
<style>
html { 
  font-size: 12px; 
}
</style>

<body>{% block navi %}
<nav class="navbar navbar-expand-sm sticky-top navbar-dark bg-primary mt-3 mb-3">
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav4" aria-controls="navbarNav4" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <a class="navbar-brand" href="{% url 'applicantctl:index' %}">応募者管理システム(applicantctl-django)</a>
    <div class="collapse navbar-collapse justify-content-end">
        <ul class="navbar-nav">
            <li class="nav-item active">
                {% if user.is_authenticated %}
					<a class="nav-link"  href="{% url 'logout' %}" class="logout">Logout({{ user.first_name}} {{ user.last_name}})</a>
				{% else %}
	                <a class="nav-link" href="{% url 'accounts:signup' %}" class="signup">Sign up</a></li>
					<a class="nav-link" href="{% url 'login' %}" class="login">Login</a>
                {% endif %}
            </li>
        </ul>
    </div>
</nav>
{% endblock %}
{% block content %}{% endblock %}
{% block fotter %}
<footer class="footer mt-auto py-3 text-right">
    <span class="text-right">Copyright [コピーライト] 2019 Makoto Inc. All Rights Reserved.</span>
</footer>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
{% endblock %}
<script src="{% static 'applicantctl/bootstrap-4.3.1-dist/js/jquery-3.4.1.min.js' %}"></script>
<script src="{% static 'applicantctl/bootstrap-4.3.1-dist/js/bootstrap.bundle.min.js' %}"></script>
</body>
</html>


(4) カレンダー利用画面用のテンプレート
  (Baseテンプレートを継承)

  base_datetimepicker.html
{% extends 'base.html' %}
{% load static %}
{% block head_meta %}

<script src="{% static 'applicantctl/bootstrap-4.3.1-dist/js/jquery-3.4.1.min.js' %}"></script>
<script src="{% static 'applicantctl/popper.js/popper.min.js' %}"></script>
<script src="{% static 'applicantctl/bootstrap-4.3.1-dist/js/bootstrap.min.js' %}"></script>

<!--bootstrap css-->
<!--local datapicker-->

<!--form.media-->
<link href="{% static 'applicantctl/bootstrap-datetimepicker_4.17.47/css/bootstrap-datetimepicker.css' %}" type="text/css" media="all" rel="stylesheet">
<link href="/static/bootstrap_datepicker_plus/css/datepicker-widget.css" type="text/css" media="all" rel="stylesheet">
<script type="text/javascript" src="{% static 'applicantctl/moment-2.9.0/moment-with-locales.min.js' %}"></script>
<script type="text/javascript" src="{% static 'applicantctl/bootstrap-datetimepicker.min.js_4.17.47/cdnjs/bootstrap-datetimepicker.min.js' %}"></script>
<script type="text/javascript" src="/static/bootstrap_datepicker_plus/js/datepicker-widget.js"></script> 


{% endblock %}

{% block content %}{% endblock %}



(5) 追加画面用のhtmlテンプレート
  1行目に、 base_datetimepicker.html を指定
  js、cssをリンクするだけで特にhtmlの内容を気にする必要は無い

  upd.html
{% extends "base_datetimepicker.html" %}
{% block content %}
</br>
{% if errmsg %}
<p class="alert alert-danger">{{ errmsg }}</p>
{%endif%}


<!--
{% for field, errors in form.errors.items %}
    {% for error in errors %}
        <p class="alert alert-danger">{{ error }}</p>
    {% endfor %}
{% endfor %}
-->

</br>

<form name="form" method="post" action="{% url 'applicantctl:upd' key_applicant %}">
		{% csrf_token %}
		<div class="container">
		{{ form.as_p }}	
		</div>
			</br>
			<div class="row">
			<div class="col-md-2">
			</div>
			<div class="col-md-2">
				<input type="button" class="btn btn-block btn-primary" OnClick="ButtonClick('1');" value="更新" >
			</div>
			<div class="col-md-2">
				<input type="button" class="btn btn-block btn-primary" OnClick="ButtonClick('2');" value="削除" >
			</div>
			<div class="col-md-6">
			</div>
		</div>
		</br>
	</div>
</form>


</br>
<script>
function ButtonClick(param){
	if (param == '2' ){
		document.form.action ="{% url 'applicantctl:delete' key_applicant %}";
		var result = confirm('削除してよろしいですか?' );
		if (result){
			document.form.submit();
		}
	}else{
		document.form.submit();
	}
}
</script>
{% endblock%}



(6) formクラスの変更
  追加日付項目という名前でDatePickerInputで年月表示のしカレンダーが表示されるように指定(14-24行目)
  ・日付フォーマットを、"%Y/%m"として指定しています。(18行目)
  ・optionで、ja(日本)と、months(年月表示)を指定している。(20-21行目)

(7) modelFormクラスの変更
  ・Metaクラス内で、年月日表示のしカレンダーが表示されるように指定(50-54行目)
  ・日付フォーマットを、"%Y/%m/%d"として指定しています。(51行目)
  ・optionで、ja(日本)を指定している。(52-54行目)

※当然ですが日付やオプションの指定方法は、Django-bootstrap-datepicker-plusでの指定方法となります。
 Bootstrap DatePickerやDateTimePickerの指定方法とは異なります。

  forms.py
import bootstrap_datepicker_plus as datetimepicker

#########################################
# 応募者登録フォーム
class T_Applicant_infoForm(forms.ModelForm):

    #
    #追加の場合はこれでOK
    #date_field = forms.DateField(
    #    widget=datetimepicker.DatePickerInput(format='%Y/%m/%d',)
    #    , label='追加日付項目'
    #)

    date_field = forms.DateField(
        label='追加日付項目',
        required = False,
        widget=datetimepicker.DatePickerInput(
            format='%Y/%m',
            options={
                'locale':'ja',
                'viewMode' : 'months'
            }
        )
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field in self.fields.values():
            field.widget.attrs['class'] = 'form-control'
        #self.fields["u_date"].required = False
        self.fields['u_date'].widget = forms.HiddenInput()

    class Meta:
        model = T_Applicant_info
        fields = ( 
            'applicant_date',
            'key_appl_route',
            'applicant_no',
            'applicant_name_text',
            'key_history_kbn',
            'u_date',
        )
        error_messages = {
            'applicant_no' : { 'required': '必須です!'
            },
            'applicant_name_text' : { 'required': '必須です!'
            }
        }
        widgets = {
            'applicant_date':datetimepicker.DatePickerInput(
                format='%Y/%m/%d',
                options={
                    'locale':'ja',
                }
            ),

        }




蛇足ですが、formatを %y/%m と年月にするとカレンダはそのように動作しましたが、
is_validで日付フォーマットではないとエラーになります。(まーとうぜんですね)



3.確認
 サーバを起動。
 画面レイアウトが少々ダサイのは、おいておいて、
 とりあえず bootstrapとして表示出来た。

WS000041.JPG
年月日バージョン
WS000042.JPG
年月バージョン
WS000034.JPG
ページング機能のレイアウトも以前より良い感じです。
ページング機能の掲載は別ページで。


中身を確認
実際に出力されたHTMLは下記内容となった。
応募日( ModelForm側 )の出力されたHTML
	<p><label for="id_applicant_date">応募日:</label> <div class="input-group date">
    <input type="text" name="applicant_date" value="2019/10/31" class="form-control" required id="id_applicant_date" dp_config="{&quot;id&quot;: &quot;dp_2&quot;, &quot;picker_type&quot;: &quot;DATE&quot;, &quot;linked_to&quot;: null, &quot;options&quot;: {&quot;showClose&quot;: true, &quot;showClear&quot;: true, &quot;showTodayButton&quot;: true, &quot;locale&quot;: &quot;ja&quot;, &quot;format&quot;: &quot;YYYY/MM/DD&quot;}}"/>
    <div class="input-group-addon input-group-append" data-target="#datetimepicker1" data-toggle="datetimepickerv">
        <div class="input-group-text"><i class="glyphicon glyphicon-calendar"></i></div>
    </div>

2行目のパラメータがエンコードされていて見づらいのでデコードすると下記のようになります。
ここでパラメータを指定していました。
	<p><label for="id_applicant_date">応募日:</label> <div class="input-group date">
    <input type="text" name="applicant_date" value="2019/10/31" class="form-control" required id="id_applicant_date" dp_config="{"id": "dp_2", "picker_type": "DATE", "linked_to": null, "options": {"showClose": true, "showClear": true, "showTodayButton": true, "locale": "ja", "format": "YYYY/MM/DD"}}"/>
    <div class="input-group-addon input-group-append" data-target="#datetimepicker1" data-toggle="datetimepickerv">
        <div class="input-group-text"><i class="glyphicon glyphicon-calendar"></i></div>
    </div>



追加項目( From側 )の出力されたHTML
<p><label for="id_date_field">追加日付項目:</label> <div class="input-group date">
    <input type="text" name="date_field" class="form-control" id="id_date_field" dp_config="{&quot;id&quot;: &quot;dp_1&quot;, &quot;picker_type&quot;: &quot;DATE&quot;, &quot;linked_to&quot;: null, &quot;options&quot;: {&quot;showClose&quot;: true, &quot;showClear&quot;: true, &quot;showTodayButton&quot;: true, &quot;locale&quot;: &quot;ja&quot;, &quot;viewMode&quot;: &quot;months&quot;, &quot;format&quot;: &quot;YYYY/MM&quot;}}"/>
    <div class="input-group-addon input-group-append" data-target="#datetimepicker1" data-toggle="datetimepickerv">
        <div class="input-group-text"><i class="glyphicon glyphicon-calendar"></i></div>
    </div>

こちらもデコードすると下記のようになります。ここでパラメータを指定していました。
<p><label for="id_date_field">追加日付項目:</label> <div class="input-group date">
    <input type="text" name="date_field" class="form-control" id="id_date_field" dp_config="{"id": "dp_1", "picker_type": "DATE", "linked_to": null, "options": {"showClose": true, "showClear": true, "showTodayButton": true, "locale": "ja", "viewMode": "months", "format": "YYYY/MM"}}"/>
    <div class="input-group-addon input-group-append" data-target="#datetimepicker1" data-toggle="datetimepickerv">
        <div class="input-group-text"><i class="glyphicon glyphicon-calendar"></i></div>
    </div>


良く見ると data-target で指定しているのが両者ともに"#datetimepicker1"を指定している。
他のDatePickerだと、JavaScriptで下記のような記載が必要なのだが、
Django-bootstrap-datepicker-plusでは不要のようです。
しかも同じ名前でもうまく動くというのが少々不思議ですが・・。
<script type="text/javascript">
 	$('#datetimepicker1').datepicker();
</script>


全ソースは、こちらに保存
https://github.com/MakotoPlus/PycharmProjects4

補足
DatePickerは、いろんな種類があるようです。
https://qiita.com/knt45/items/6d74f6785cd4547ae53b
自分は、 DateTimePicker と Bootstrap DatePicker が同じものだと勘違いしていました・・。
https://ascii.jp/elem/000/000/883/883101/
ちょっと認識間違えでハマりました・・。

Bootstrap DatePicker は、 Bootstrapで用意されているDatePicker であって、
DateTimePickerは、Jquery pluginを利用したカレンダのようである。
そして、Django用Datepckerライブラリが、django-bootstrap-datepicker-plusです。
こちら、datepickerと言いながら、利用時は、datetimepckerと「time」を付けるので
混乱する理由となった(イイワケ)

Bootstrap DatePicker
https://uxsolutions.github.io/bootstrap-datepicker/?markup=input&format=&weekStart=&startDate=&endDate=&startView=0&minViewMode=0&maxViewMode=4&todayBtn=false&clearBtn=false&language=en&orientation=auto&multidate=&multidateSeparator=&keyboardNavigation=on&forceParse=on#sandbox
DateTimePicker
https://xdsoft.net/jqplugins/datetimepicker/
Django-bootstrap-datepicker-plus
https://django-bootstrap-datepicker-plus.readthedocs.io/en/latest/Walkthrough.html

Django-bootstrap-datepicker-plusでの参考サイトは下記
https://pisuke-code.com/bootstrap-how-to-show-datepicker/
https://intellectual-curiosity.tokyo/2018/11/09/django%E3%81%A7datepicker%EF%BC%88%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E3%81%AB%E3%82%88%E3%82%8B%E6%97%A5%E6%99%82%E5%85%A5%E5%8A%9B%EF%BC%89%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B/






─都心の天然温泉─ 名古屋クラウンホテル

─都心の天然温泉─ 名古屋クラウンホテル

  • 場所: 愛知県名古屋市中区栄1-8-33
  • 特色: 天然温泉「三蔵温泉」あり。大小20室以上の会議室・宴会場あり。全室冷蔵庫・シャワートイレ完備。



nice!(0)  コメント(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

※ブログオーナーが承認したコメントのみ表示されます。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。