本記事は2ページにわたって解説しています。
はじめに
Djangoで作成したアプリケーションについて、Bootstrapでデザインを調整する方法を解説します。
今回は、前回作成した以下のCRUDアプリケーションのデザインを、Bootstrapを利用して調整します。
他にも私のブログで、Djangoについて解説している記事がありますのでご覧ください。
余談ですが、Laravel向けに解説した記事もございますので参考にしてください。
VS Codeインストール
VS Codeのインストール方法は、以下の記事にまとめましたのでご覧ください。
VS Codeのオススメ設定や拡張機能などは、以下の記事にまとめました。
共通テンプレートの作成
まずは、共通部分は共通テンプレートにしましょう。
これにより、毎回ヘッダーやフッターなどを記述しなくて済みます。
<html>
<head>
<meta charset='utf-8' />
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
画面の修正を行う例です。
以下のように共通テンプレートを読み込み、本文を記述します。
{% extends 'crud/base.html' %}
{% block content %}
本文
{% endblock %}
一覧画面は以下のように修正します。
{% extends 'crud/base.html' %}
{% block content %}
<h1>商品一覧</h1>
<a href="{% url 'crud:new' %}">新規登録</a>
<table border="1">
<thead>
<tr>
<td>商品名</td>
<td>価格</td>
<td></td>
</tr>
</thead>
{% for product in object_list %}
<tr>
<td>{{ product.name }}</td>
<td>{{ product.price }} 円</td>
<td>
<a href="{% url 'crud:edit' pk=product.pk %}">編集</a>
<a href="{% url 'crud:delete' pk=product.pk %}">削除</a>
</td>
</tr>
{% endfor %}
</table>
{# ページの表示 #}
{{ page_obj.number }} / {{ page_obj.paginator.num_pages }} ページ<br>
{# 前へ #}
{% if page_obj.has_previous %}
<a href="?page=1">« 先頭</a>
<a href="?page={{ page_obj.previous_page_number }}">前へ</a>
{% endif %}
{# 次へ #}
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">次へ</a>
<a href="?page={{ page_obj.paginator.num_pages }}">最後 »</a>
{% endif %}
{% endblock %}
この時点で、画面を表示してみましょう。
エラーが表示されなければOKです。
他の画面も同様に修正します。
{% extends 'crud/base.html' %}
{% block content %}
<h1>新規登録</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<a href="{% url 'crud:list' %}">戻る</a>
<input type="submit" value="登録">
</form>
{% endblock %}
{% extends 'crud/base.html' %}
{% block content %}
<h1>編集</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<a href="{% url 'crud:list' %}">戻る</a>
<input type="submit" value="編集">
</form>
{% endblock %}
{% extends 'crud/base.html' %}
{% block content %}
<h1>削除</h1>
<form method="post">
{% csrf_token %}
以下の商品を削除してもよろしいですか?<br>
{{ object }}<br>
{{ form }}
<a href="{% url 'crud:list' %}">戻る</a>
<input type="submit" value="削除">
</form>
{% endblock %}
Bootstrap導入
Bootstrapを導入します。
CDNを利用しますが、最新である5系を使用します。
共通テンプレートを修正します。
これでBootstrapの導入ができました。
<!doctype html>
<html>
<head>
<meta charset='utf-8' />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
{% block content %}{% endblock %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
</body>
</html>
今回はナビゲーションバーを設置してみました。
<!doctype html>
<html>
<head>
<meta charset='utf-8' />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<style>
body {
padding-top: 70px;
}
</style>
</head>
<body>
<header>
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">CRUD</a>
</div>
</nav>
</header>
<div class="container">
{% block content %}{% endblock %}
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
</body>
</html>
このような画面になりました。
django-widget-tweaks
新規登録画面など、現状は以下の一行でフォームに関するHTMLタグを出力しています。
{{ form.as_p }}
この場合、各タグにCSSクラスを追加したい場合に不便です。
実際にデザインを調整する上で、クラスの指定やタグの追加などを行いますので、今回は「django-widget-tweaks」を使用します。
今回はVS Codeを使い、Dockerコンテナで作業していますので、以下のファイルを修正します。
一番最後の行を追加します。(django-widget-tweaks)
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN pip install django
RUN pip install mysqlclient
RUN pip install django-widget-tweaks
F1キーをクリックし、コンテナをリビルドします。(Dev Containers: Rebuild Container)
settings.pyを修正し、django-widget-tweaksを読み込みます。
INSTALLED_APPS = [
...
'widget_tweaks',
'crud',
]
使い方は以下のような感じです。
{% load widget_tweaks %}
<!-- add 2 extra css classes to field element -->
{{ form.title|add_class:"css_class_1 css_class_2" }}
一覧画面の修正
一覧画面のテーブルやページネーションの調整を行います。
{% extends 'crud/base.html' %}
{% block content %}
<h1>商品一覧</h1>
<a class="btn btn-light" href="{% url 'crud:new' %}">新規登録</a>
<table class="table">
<thead>
<tr>
<td>商品名</td>
<td>価格</td>
<td></td>
</tr>
</thead>
{% for product in object_list %}
<tr>
<td>{{ product.name }}</td>
<td>{{ product.price }} 円</td>
<td>
<a class="btn btn-primary" href="{% url 'crud:edit' pk=product.pk %}">編集</a>
<a class="btn btn-danger" href="{% url 'crud:delete' pk=product.pk %}">削除</a>
</td>
</tr>
{% endfor %}
</table>
<div class="d-flex justify-content-between">
<div>
{# ページの表示 #}
{{ page_obj.number }} / {{ page_obj.paginator.num_pages }} ページ<br>
</div>
<div class="btn-group">
{# 前へ #}
{% if page_obj.has_previous %}
<a class="btn btn-outline-secondary" href="?page=1">« 先頭</a>
<a class="btn btn-outline-secondary" href="?page={{ page_obj.previous_page_number }}">前へ</a>
{% else %}
<a class="btn btn-outline-secondary disabled">« 先頭</a>
<a class="btn btn-outline-secondary disabled">前へ</a>
{% endif %}
{# 次へ #}
{% if page_obj.has_next %}
<a class="btn btn-outline-secondary" href="?page={{ page_obj.next_page_number }}">次へ</a>
<a class="btn btn-outline-secondary" href="?page={{ page_obj.paginator.num_pages }}">最後 »</a>
{% else %}
<a class="btn btn-outline-secondary disabled">次へ</a>
<a class="btn btn-outline-secondary disabled">最後 »</a>
{% endif %}
</div>
</div>
{% endblock %}
以下のURLにアクセスし確認しましょう。
http://localhost:8000/crud/
一覧画面が表示されました。
新規登録ボタンや編集、削除、そしてページネーションのデザインが調整されました。
引き続き、新規登録画面の修正を行います。
コメント