Bootstrapは、WEBページでよく使われるフォーム、ボタン、メニューなどの部品がテンプレートとして用意されているフレームワークで、Bootstrapを利用すると、見栄えのいいWEBサイトを簡単に作成することができる。
今回は、作成済の「Django」を利用したアプリケーションを、「Bootstrap」でデザインしてみたので、そのサンプルプログラムを共有する。
なお、Bootstrapについては、以下のサイトを参照のこと。
https://www.sejuku.net/blog/7407
Bootstrap ダウンロード
Bootstrapは、WEBサイトから無料でダウンロードして利用することができる。その手順は、以下の通り。
1) 以下のサイトにアクセスし、「ダウンロード」ボタンを押下する。
https://getbootstrap.jp

2) 以下の画面に遷移するため、「コンパイルされたCSSとJS」にある「Download」ボタンを押下する。

3)「bootstrap-5.0.2-dist.zip」がダウンロードされるため、解凍する。

4) 今回のサンプルプログラムでは、Bootstrapを解凍したフォルダ内の、「bootstrap.min.css」「bootstrap.bundle.min.js」を利用する。

サンプルプログラムの作成
作成したサンプルプログラムの構成は、以下の通り。

なお、上記の赤枠は、前提条件のプログラムから追加・変更したプログラムである。
「bootstrap.min.css」「bootstrap.bundle.min.js」は、ダウンロードしたBootstrapのCSSファイル/JSファイルとなる。
demoフォルダ下、templatesフォルダ下の各画面の内容は以下の通りで、Bootstrapを利用するようにしている。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>一覧画面</title>
<!-- BootStrap CSS/JSファイルの読み込み -->
{% load static %}
<link rel="stylesheet" href="{% static 'demo/css/bootstrap.min.css' %}">
<script src="{% static 'demo/js/bootstrap.bundle.min.js' %}"></script>
</head>
<body>
<!-- 画面サイズを画面幅いっぱい(container-fluid)とし、marginを上下左右に設定 -->
<div class="container-fluid m-4">
<!-- タイトル行の文字サイズを設定 -->
<p class="fs-4">ユーザーデータテーブル(user_data)の全データ</p>
<!-- 表の幅を、画面横幅の11/12の長さに設定 -->
<div class="col-11">
<!-- テーブルの1行おきに背景色を設定 -->
<table class="table table-striped">
<!-- テーブルのタイトル行を水色に設定 -->
<tr class="table-info">
<th>ID</th>
<th>名前</th>
<th>生年月日</th>
<th>性別</th>
<th></th>
<th></th>
</tr>
<!-- context_object_nameで指定した一覧取得結果を画面に表示 -->
{% for user in user_list %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.birth_year }}年
{{ user.birth_month }}月
{{ user.birth_day }}日
</td>
<td>
{% if user.sex|stringformat:"s" == "1" %}
男
{% elif user.sex|stringformat:"s" == "2" %}
女
{% endif %}
</td>
<td>
<a href="{% url 'update' user.id %}">更新</a>
</td>
<td>
<a href="{% url 'delete' user.id %}">削除</a>
</td>
</tr>
{% endfor %}
</table>
</div>
<!-- action属性のURLで、(demoフォルダ内)urls.pyの画面遷移先のname属性の値を指定している -->
<form action="{% url 'input' %}" method="post">
<!-- 下記csrf_tokenは、CSRF対策を行うことでform送信時エラーを防ぐために設定 -->
{% csrf_token %}
<!-- marginを上に設定 -->
<div class="mt-5">
<!-- ボタンの色を青色に設定 -->
<input type="submit" name="next" value="データ追加"
class="btn btn-primary"/>
</div>
</form>
</div>
</body>
</html><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>入力画面</title>
<!-- BootStrap CSS/JSファイルの読み込み -->
{% load static %}
<link rel="stylesheet" href="{% static 'demo/css/bootstrap.min.css' %}">
<script src="{% static 'demo/js/bootstrap.bundle.min.js' %}"></script>
</head>
<body>
<!-- 画面サイズを画面幅いっぱい(container-fluid)とし、marginを上下左右に設定 -->
<div class="container-fluid m-4">
<!-- タイトル行の文字サイズを設定 -->
<p class="fs-4">下記必要事項を記載の上、「確認」ボタンを押下してください。</p>
<!-- action属性のURLで、(demoフォルダ内)urls.pyの画面遷移先のname属性の値を指定している -->
<form action="{% url 'confirm' %}" method="post">
<!-- 下記csrf_tokenは、CSRF対策を行うことでform送信時エラーを防ぐために設定 -->
{% csrf_token %}
<!-- 表の幅を、画面横幅の9/12の長さに設定 -->
<div class="col-9">
<!-- テーブルの枠線を非表示に設定 -->
<table class="table table-borderless">
<!-- 名前 -->
<tr>
<!-- 画面幅が広くなるにつれてラベルのサイズを狭める設定 -->
<td class="col-md-4 col-lg-2">
<!-- フォームとラベルの関連付けを設定 -->
<label for="name" class="form-label">
{{ form.name.label_tag }}
</label>
</td>
<td>
<span id="name" class="form-label">
{{ form.name }}
</span>
</td>
</tr>
<!-- 生年月日 -->
<tr>
<td>{{ form.birth_day.label_tag }}</td>
<td>
{{ form.birth_year }}年
{{ form.birth_month }}月
{{ form.birth_day }}日
<!-- 生年月日の入力チェックエラーを表示 -->
<span class="text-danger">
{{ form.non_field_errors.0 }}
</span>
</td>
</tr>
<!-- 性別 -->
<tr>
<td>{{ form.sex.label_tag }}</td>
<td>
{% for sex_choice in form.sex %}
<span class="me-2">
{{ sex_choice.choice_label }}
{{ sex_choice.tag }}
</span>
{% endfor %}
</td>
</tr>
<!-- メモ -->
<tr>
<td>
<label for="memo" class="form-label">
{{ form.memo.label_tag }}
</label>
</td>
<td>
<span id="memo" class="form-label">
{{ form.memo }}
</span>
</td>
</tr>
<!-- 入力確認 -->
<tr>
<td>
<label for="check" class="form-label">
{{ form.check.label_tag }}
</label>
</td>
<td>
<span id="check" class="form-label">
{{ form.check }}
</span>
</td>
</tr>
</table>
</div>
<!-- ユーザーID -->
<!-- 一覧画面で更新リンクを押下したため、object.idが設定されている場合 -->
{% if object.id %}
<input type="hidden" name="user_id" value="{{ object.id }}"/>
<!-- 入力画面で入力チェックエラーが発生したり、確認画面で戻るボタンを
押下したため、user_idが設定されている場合 -->
{% elif user_id %}
<input type="hidden" name="user_id" value="{{ user_id }}"/>
<!-- 一覧画面でデータ追加ボタンを押下したため、object.idもuser_idも
設定されていない場合 -->
{% else %}
<input type="hidden" name="user_id" value=""/>
{% endif %}
<!-- marginを上に設定 -->
<div class="mt-5">
<!-- ボタンの色を青色に設定 -->
<input type="submit" name="confirm" value="確認"
class="btn btn-primary"/>
<!-- marginを左に設定 -->
<span class="ms-4">
<input type="button" name="back" value="戻る"
class="btn btn-primary"
onclick="location.href={% url 'index' %}"/>
</span>
</div>
</form>
</div>
</body>
</html><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>確認画面</title>
<!-- BootStrap CSS/JSファイルの読み込み -->
{% load static %}
<link rel="stylesheet" href="{% static 'demo/css/bootstrap.min.css' %}">
<script src="{% static 'demo/js/bootstrap.bundle.min.js' %}"></script>
</head>
<body>
<!-- 画面サイズを画面幅いっぱい(container-fluid)とし、marginを上下左右に設定 -->
<div class="container-fluid m-4">
<!-- タイトル行の文字サイズを設定 -->
<p class="fs-4">入力内容を確認し、問題なければ「送信」ボタンを押下してください。</p>
<form action="{% url 'regist' %}" method="post">
{% csrf_token %}
<!-- 表の幅を、画面横幅の8/12の長さに設定 -->
<div class="col-8">
<!-- テーブルの枠線を非表示に設定 -->
<table class="table table-borderless">
<!-- 名前 -->
<tr>
<!-- 画面幅が広い場合にラベルのサイズを狭める設定 -->
<td class="col-md-4 col-lg-2">
{{ input_form.name.label_tag }}
</td>
<td>{{ input_form.name.value }}</td>
</tr>
<!-- 生年月日 -->
<tr>
<td>{{ input_form.birth_day.label_tag }}</td>
<td>
{{ input_form.birth_year.value }}年
{{ input_form.birth_month.value }}月
{{ input_form.birth_day.value }}日
</td>
</tr>
<!-- 性別 -->
<tr>
<td>{{ input_form.sex.label_tag }}</td>
<td>{{ lbl_sex }}</td>
</tr>
<!-- メモ -->
<tr>
<td>{{ input_form.memo.label_tag }}</td>
<td>
<!-- テキストエリアの改行を有効にするため、「| linebreaksbr」を付与 -->
{{ input_form.memo.value | linebreaksbr }}
</td>
</tr>
<!-- 入力確認 -->
<tr>
<td>{{ input_form.check.label_tag }}</td>
<td>{{ lbl_checked }}</td>
</tr>
</table>
</div>
<!-- ユーザーID -->
<input type="hidden" name="user_id" value="{{ user_id }}"/>
<!-- フォームの各値を次画面に渡すためhidden項目を設定 -->
{% for field in input_form %}
{{field.as_hidden}}
{% endfor %}
<!-- marginを上に設定 -->
<div class="mt-5">
<!-- ボタンの色を青色に設定 -->
<input type="submit" name="send"
class="btn btn-primary" value="送信"/>
<!-- marginを左に設定 -->
<span class="ms-4">
<input type="submit" name="back"
class="btn btn-primary" value="戻る"/>
</span>
</div>
</form>
</div>
</body>
</html><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>完了画面</title>
<!-- BootStrap CSS/JSファイルの読み込み -->
{% load static %}
<link rel="stylesheet" href="{% static 'demo/css/bootstrap.min.css' %}">
<script src="{% static 'demo/js/bootstrap.bundle.min.js' %}"></script>
</head>
<body>
<!-- 画面サイズを画面幅いっぱい(container-fluid)とし、marginを上下左右に設定 -->
<div class="container-fluid m-4">
<!-- タイトル行の文字サイズを設定 -->
<p class="fs-4">お申し込みが完了しました。</p>
<!-- marginを上に設定 -->
<div class="mt-5">
<!-- ボタンの色を青色に設定 -->
<input type="button" name="back" value="一覧画面に戻る"
class="btn btn-primary"
onclick="location.href={% url 'index' %}"/>
</div>
</div>
</body>
</html><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>削除確認画面</title>
<!-- BootStrap CSS/JSファイルの読み込み -->
{% load static %}
<link rel="stylesheet" href="{% static 'demo/css/bootstrap.min.css' %}">
<script src="{% static 'demo/js/bootstrap.bundle.min.js' %}"></script>
</head>
<body>
<!-- 画面サイズを画面幅いっぱい(container-fluid)とし、marginを上下左右に設定 -->
<div class="container-fluid m-4">
<!-- タイトル行の文字サイズを設定 -->
<p class="fs-4">下記データを削除する場合は、「削除」ボタンを押下してください。</p>
<form method="post">
<!-- 下記csrf_tokenは、CSRF対策を行うことでform送信時エラーを防ぐために設定 -->
{% csrf_token %}
<!-- 表の幅を、画面横幅の8/12の長さに設定 -->
<div class="col-8">
<!-- テーブルの枠線を非表示に設定 -->
<table class="table table-borderless">
<!-- 名前 -->
<tr>
<!-- 画面幅が広い場合にラベルのサイズを狭める設定 -->
<td class="col-md-4 col-lg-2">
名前:
</td>
<td>{{ object.name }}</td>
</tr>
<!-- 生年月日 -->
<tr>
<td>生年月日:</td>
<td>
{{ object.birth_year }}年
{{ object.birth_month }}月
{{ object.birth_day }}日
</td>
</tr>
<!-- 性別 -->
<tr>
<td>性別:</td>
<td>
{% if object.sex|stringformat:"s" == "1" %}
男
{% elif object.sex|stringformat:"s" == "2" %}
女
{% endif %}
</td>
</tr>
<!-- メモ -->
<tr>
<td>メモ:</td>
<td>
<!-- 「| default:""」で、Noneを空文字に置き換える -->
<!-- テキストエリアの改行を有効にするため、「| linebreaksbr」を付与 -->
{{ object.memo | default:"" | linebreaksbr }}
</td>
</tr>
</table>
</div>
<!-- marginを上に設定 -->
<div class="mt-5">
<!-- 削除ボタンの色を赤色に設定 -->
<input type="submit" value="削除" class="btn btn-danger"/>
<!-- marginを左に設定 -->
<span class="ms-4">
<!-- 戻るボタンの色を青色に設定 -->
<input type="button" name="back" value="戻る"
class="btn btn-primary"
onclick="location.href={% url 'index' %}"/>
</span>
</div>
</form>
</div>
</body>
</html>その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/python/tree/master/django-bootstrap/djangoApp
サンプルプログラムの実行
サンプルプログラムの実行結果は以下の通りで、各画面がBootstrapでデザインされていることが確認できる。
1) 実行前のuser_dataテーブルの中身は、以下の通り。
select * from user_data

2) コマンドプロンプトでDjangoプロジェクト名のフォルダに移動し、コマンドプロンプトで「python manage.py runserver」コマンドを実行して、Webサーバーを起動する。

3) Webブラウザを起動し、「http://127.0.0.1:8000/demo/」にアクセスすると、以下のように、user_dataテーブルの中身が一覧画面(list.html)に表示されることが確認できる。

4) 上記画面で「データ追加」ボタンを押下すると、以下のように、入力画面(input.html)が表示されることが確認できる。

5) 入力画面(input.html)でエラーが発生した場合のレイアウトは、以下の通り。

6) 確認画面(confirm.html)のレイアウトは、以下の通り。

7) 完了画面(complete.html)のレイアウトは、以下の通り。

8) 一覧画面(list.html)で、ID=4の「更新」リンクを押下すると、以下のように、該当するデータが入力画面に表示されることが確認できる。


9) 一覧画面(list.html)で、ID=4の「削除」リンクを押下すると、以下のように、該当するデータが削除確認画面に表示されることが確認できる。


要点まとめ
- Bootstrapは、WEBページでよく使われるフォーム、ボタン、メニューなどの部品がテンプレートとして用意されているフレームワークで、Bootstrapを利用すると、見栄えのいいWEBサイトを簡単に作成することができる。
- Pythonフレームワーク「Django」を利用したアプリケーションでも、「Bootstrap」を利用できる。





