【第6回】Djangoで日記アプリを作ろう ~Djangoテンプレート言語編~
エンジニアになろう!
【第6回】Djangoで日記アプリを作ろう ~Djangoテンプレート言語編~
前回は、UpdateView と DeleteView を利用して、日記の編集画面と削除画面を作成しました。
今回は、Django テンプレート言語を利用して、画面の装飾を工夫してみましょう。
上記機能の作成を通して、以下の内容を新しく学んでいきます。
- Django テンプレート言語とは?
- テンプレートの継承
- widget を利用してフォームに class 属性を付与する方法
- django-widget-tweak の使い方
- django で bootstrap4 を利用する方法
それではまず、Django テンプレート言語について学んでいきましょう!
Djangoテンプレート言語とは
Django テンプレートとは、Django において HTML を生成するための仕組みです。
そして、Django テンプレート言語は、その HTML 生成を支援する言語です。
この言語を利用することで、テンプレートの中に動的なコンテンツを、簡単に埋め込むことができます。
実を言うと、この言語はこれまでの連載の中で、たくさん利用してます。
HTML に、フォームを作成するための、 {{ form }} という記述を行なっていました。
これがまさしく、テンプレート言語を用いた表現です。
今回は、まず Django テンプレート言語の基本概念である、「変数」と「タグ」を学びましょう。
また、テンプレートの継承という概念を利用して、以下の2つをあげる取り組みをしていきましょう。
- これまで作成したテンプレートの可読性
- 作成効率
変数
Django テンプレート言語では、 {{ }} という表現は、変数と呼ばれます。
主にビューで処理したデータを、テンプレート内部で利用するために使います。
これまで、CreateView や DetailView を用いて、日記の作成画面や詳細画面を作ってきました。
それらビューは、フォームや日記詳細データを、form や diary といった変数に与えます。
Django テンプレート言語では、それら変数を {{ }} という形で呼び出し、テンプレート内部で利用することができるわけです。
タグ
テンプレート言語では、もう一つ代表的な表現があります。
それがタグと呼ばれるもので、 {% %} というように表現されます。
主にタグは、Django テンプレートが用意する、組み込み機能を利用する場合に利用されます。
例えば、 {% now "Y年m月d日" %} というタグは、現在時刻を Y 年 m 月 d 日 形式で、HTML 上に表示します。
このような便利な組み込みタグがあるので、動的なコンテンツでも簡単なものであれば、ビューで実装する必要性はありません。
次の章では、「block タグ」と「extends タグ」を利用して、テンプレートの継承という操作を行なっていきましょう。
テンプレートの継承とは
テンプレートの継承とは、まず画面レイアウトの雛形となる「親テンプレート」を作り、その親テンプレートに各画面独自のコンテンツを加えてテンプレートを作成していくことです。
Web ページは、大きく分けると、以下の3つで構成されています。
- ヘッダー
- ボディ
- フッター
ヘッダーやフッターは、全てのページ共通といったこともよくありますね。
その場合は、まずページ共通の部分であるヘッダーとフッターを、親テンプレートで定義します。
そのテンプレートを継承する形で、他のテンプレートを作成していけば、同じ内容をコーディングする必要がありません。
また、ヘッダーやフッターの改修のとき、親テンプレートさえ変えてあげれば OK です。
これなら、改修コストも大きく削減できますね!
親テンプレートの作成
今回は、これまで作成してきたテンプレートから、共通の部分を抜き出した親テンプレートを作成してみます。
templates ディレクトリに、base.html という名前で、テンプレートを作成しましょう。
それに、以下のようなコードを記述して下さい。
1<!DOCTYPE html>
2<html lang="jp">
3<head>
4 <meta charset="UTF-8">
5 <title>MyDjangoApp</title>
6</head>
7<body>
8{% block content %}
9{% endblock %}
10</body>
11</html>
日記投稿画面や日記の編集画面などで、共通の内容を抜き出してきました。
base.htmlのポイント
先ほどの html ファイルのポイントは、1つだけです。
<body>タグの中に記載された
1{% block content %}
2{% endblock %}
の部分です。
base.html を継承したテンプレートでは、このブロックの部分にテンプレート独自の要素を追加することができます。
content という部分は、このブロックの名前です。
content という名前のブロックだけでなく、異なる名前の付いたブロックを作成することもできます。
既存テンプレートを継承した形に改修
index.html
では試しに、index.html を、親テンプレートを継承した形に改修してみましょう!
1{% extends 'base.html' %}
2{% block content %}
3<h1>Diary App by Django</h1>
4<h2><a href="{% url 'diary:diary_create' %}">日記の投稿</a></h2>
5<h2><a href="{% url 'diary:diary_list' %}">日記の一覧</a></h2>
6{% endblock %}
まず index.html の冒頭にある、 {% extends 'base.html' %} というコードにより、base.html を継承しています。
そして、 {% block content %} と {% endblock %} で囲まれた内容が、base.html の content ブロックに追加されます。
ちなみに、以下のコードが、これまでの index.html です。
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <title>MyDiaryApp</title>
6</head>
7<body>
8<h1>Diary App by Django</h1>
9<h2><a href="{% url 'diary:diary_create' %}">日記の投稿</a></h2>
10<h2><a href="{% url 'diary:diary_list' %}">日記の一覧</a></h2>
11</body>
12</html>
コードの量が、約半分になっていますね。
<body>タグ以外の内容が、全て親テンプレートに吸収されています。
テンプレートの継承を利用すると、「その画面に固有の要素」が浮き彫りになりますので、保守性がぐっと上がります。
他のテンプレートも継承利用へ改修
他の全てのテンプレートも、テンプレートの継承を利用した形に改修してみましょう。
見本として、「diary_create.html」と「diary_update.html」を、テンプレートを利用した形式に改修したものを記載します。
diary_create.html テンプレート継承バージョン
1{% extends 'base.html' %}
2{% block content %}
3<h1>日記の作成</h1>
4<form method="post">
5 {% csrf_token %}
6 {{ form.as_p }}
7 <button type="submit">投稿</button>
8</form>
9{% endblock %}
diary_update.html テンプレート継承バージョン
1{% extends 'base.html' %}
2{% block content %}
3<h1>日記の編集</h1>
4<form method="post">
5 {% csrf_token %}
6 {{ form.as_p }}
7 <input type="submit" value="保存">
8</form>
9{% endblock %}
class属性の付け方
ここからは、画面のデザインを整えていくことにフォーカスしていきます。
画面デザインを整える方法として代表的なものが、Bootstrap を利用すること。
Bootstrap では、見た目を変えたい html 要素に適切なクラスを設定することで、自動的にプリセットデザインが反映されます。
Django でも、テンプレート内部の html 要素に、従来通り class 属性を与えてあげれば OK です。
ただし、いくつかの要素には問題があります。
問題の例
例えばフォームです。
今回の記事で学んだ通り、フォームは Django テンプレート言語の変数を利用して、{ form } といった形で表現されます。
この変数に対して、{ form class="form-class" } としてもダメです…。
Django において、フォームを定義しているのは、forms.py に定義されたフォームクラス。
このフォームクラスを変更して、class 属性を追加する方法を学びましょう!
formクラスにclass属性を追加しよう
diary ディレクトリ内の forms.py には、DiaryForm クラスが定義されています。
この DiaryForm クラスを改修して、以下の3つに class 属性を付与します。
- date
- title
- text
DiaryForm クラスを、以下のように変えてみましょう。
1from django import forms
2from .models import Diary
3
4
5class DiaryForm(forms.ModelForm):
6 class Meta:
7 model = Diary
8 fields = ('date', 'title', 'text')
9 widgets = {
10 'date': forms.DateInput(attrs={'class': 'form-control'}),
11 'title': forms.TextInput(attrs={'class': 'form-control'}),
12 'text': forms.TextInput(attrs={'class': 'form-control'}),
13 }
ポイントはwidget
ポイントは、 Meta クラス内部に定義された、widget というフィールドです。
この widget は、辞書型のデータを持っています。
キーが form のフィールド値、バリューがフォームの種類を定める、ウィジェットと呼ばれるクラスです。
このウィジェットの種類や、クラス引数を変えることにより、テンプレートに埋め込まれるフォームの種類や属性値が変わります。
attrs というクラス引数を見ると、class をキーとして、バリューが form-control となっていますね。
これにより、form-contol という class 属性が、各フォームに付与されます。
この改修を終えたら、一度 Django プロジェクトを起動してみましょう。
Chromeデベロッパーツールで確認
Chrome デベロッパーツールで、日記投稿画面の実装を確認すると、以下のようになっているはずです。
これでフォームに、class を設定することができました。
widget は、class を追加するだけでなく、フォームの大きさを変えたりフォームの種類を変えたりなど、フォームに関する様々な調整が可能です。
例えば、title のウィジェットを TextInput から Textarea に変更すると、以下のように html のテキストエリアが作成されます。
ウィジェットを介したclass設定には問題も…
ウィジェットを介して、class を設定する方法を学びましたが、実はこの方法には少し問題があります。
例えば、フォームに対する class 属性は、forms.py の中に定義されています。
ところが、それ以外の div タグなどの class 属性は、html ファイルの中に記述されているのです。
これでは、保守性が落ちてしまいます。
やはり class 属性ぐらいは、html ファイルの中で、全て宣言したいところ…。
これを実現するには、「django-widget-tweak」というライブラリを使えば OK です。
django-widget-tweak を利用してclass属性を追加しよう
django-widget-tweaks というライブラリを利用すれば、テンプレート内部で class 属性を定義することができます。
【GitHub:django-widget-tweaks】
https://github.com/jazzband/django-widget-tweaks
それでは、バージョン1.4.8をインストールして利用してみましょう。
terminal で、以下のコマンドを実行します。
1pip install django-widget-tweaks==1.4.8
pip show django-widget-tweaks を実行すると、以下のような出力が得られます。
1Name: django-widget-tweaks
2Version: 1.4.8
3Summary: Tweak the form field rendering in templates, not in python-level form definitions.
4Home-page: https://github.com/jazzband/django-widget-tweaks
5Author: Mikhail Korobov
6Author-email: kmike84@gmail.com
7License: MIT license
8〜省略〜
MIT license であるため、ライセンスに従えば商用利用も OK です。
インストールが完了した後は、config ディレクトリの中にある settings.py を開き、widget_tweaks アプリを追加します。
1INSTALLED_APPS = [
2 'django.contrib.admin',
3 'django.contrib.auth',
4 'django.contrib.contenttypes',
5 'django.contrib.sessions',
6 'django.contrib.messages',
7 'django.contrib.staticfiles',
8 'diary',
9 'widget_tweaks', # 追加
10]
このアプリを利用することで、例えば以下のような記述で、class 属性を付与することが可能です。
1{{ form.date | add_class:'form-control' }}
次の章では、「django-widget-tweaks」と「bootstrap」を併用して、画面の装飾を行なっていきましょう!
Bootstrap4を利用するための準備
それでは、bootsttrap を利用して、画面装飾を行なっていきましょう。
CDN で Bootstrap を利用することもできます。
ただ Django では、3rd パーティの Django アプリを介して、bootstrap を利用することも可能です。
django-bootstrap4をインストール
以下のコマンドを実行し、django-bootstrap4 をインストールしましょう!
1pip install django-bootstrap4==2.3.1
pip show django-bootstrap4 を実行すると、以下のような出力が得られます。
1Name: django-bootstrap4
2Version: 2.3.1
3Summary: Bootstrap support for Django projects
4Home-page: https://github.com/zostera/django-bootstrap4
5Author: Dylan Verheul
6Author-email: dylan@zostera.nl
7License: BSD-3-Clause
8〜省略〜
BSD-3-Clause ライセンスであるため、商用利用の際には、著作権表示や免責事項等の表示に注意しましょう。
settings.pyにbootstrap4アプリを追加
インストールが完了したら、django-widget-tweaks と同様に、settings.py に bootstrap4 アプリを追加しましょう。
1INSTALLED_APPS = [
2 'django.contrib.admin',
3 'django.contrib.auth',
4 'django.contrib.contenttypes',
5 'django.contrib.sessions',
6 'django.contrib.messages',
7 'django.contrib.staticfiles',
8 'diary',
9 'bootstrap4', # 追加
10 'widget_tweaks',
11]
settings.pyのTEMPLATESを編集
また、settings.py の TEMPLATES の編集も必要です。
TEMPLATES の builtins に、コードを追加しましょう。
1TEMPLATES = [
2 {
3 'BACKEND': 'django.template.backends.django.DjangoTemplates',
4 'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
5 'APP_DIRS': True,
6 'OPTIONS': {
7 'context_processors': [
8 'django.template.context_processors.debug',
9 'django.template.context_processors.request',
10 'django.contrib.auth.context_processors.auth',
11 'django.contrib.messages.context_processors.messages',
12 ],
13 'builtins': [
14 'bootstrap4.templatetags.bootstrap4', # 追加
15 ],
16 },
17 },
18]
この記述により、django-bootstrap4 が提供する組み込み(built in)タグを、利用できるようになります。
テンプレートの編集
では、テンプレートの編集に移っていきます。
まずは、親テンプレートである base.html の先頭に、bootstrap を利用するための記述を加えます。
1<!DOCTYPE html>
2<html lang="jp">
3{% bootstrap_css %} <!-- 追加 -- >
4<head>
5 <meta charset="UTF-8">
6 <title>MyDjangoApp</title>
7</head>
8<body>
9{% block content %}
10{% endblock %}
11</body>
12</html>
これで、base.html を継承した全テンプレートで、bootstrap を利用することができます。
diary_create.htmlを編集
続いて、diary_create.html を、以下のように編集しましょう。
1{% extends 'base.html' %}
2{% load widget_tweaks %}
3{% block content %}
4 <h1>日記の作成</h1>
5 <form method="post">
6 {% csrf_token %}
7 <div class="form-group">
8 <label>{{ form.date.label }}</label>
9 {{ form.date | add_class:'form-control col-2' }}
10 </div>
11 <div class="form-group">
12 <label>{{ form.title.label }}</label>
13 {{ form.title | add_class:'form-control col-2' }}
14 </div>
15 <div class="form-group">
16 <label>{{ form.text.label }}</label>
17 {{ form.text | add_class:'form-control col-2' }}
18 </div>
19 <button type="submit" class="form-control col-1">投稿</button>
20 </form>
21{% endblock %}
このコードには、ポイントが2つあります。
ポイント1:{% load widget_tweaks %}
まず1つ目が、2行目にある {% load widget_tweaks %} です。
この記述により、django-widget-tweaks の機能が、テンプレートの中で利用できるようになります。
load タグを利用するなら、テンプレート1つ1つに宣言が必要となるので注意して下さい。
ちなみにこのあたりの内容は、ライブラリの実装も関わってくるため、ここでは深入りはしません。
ポイント2:add_class
2つ目のポイントが、add_class です。
widget-tweak の add_class を利用して、各フォーム値にお手軽にクラス属性を付与しています。
厳密には、Django のフィルターという機能が併用されています。
また、上記テンプレートのコードは、bootstrap のフレームワークを意識してみました。
form-group と form-control を設定し、見栄えも考えて、col クラスの設定も行なっています。
Djangoプロジェクトの動作確認
長くなってしまいましが、ここまでの編集が終わったら、Django プロジェクトを起動してみましょう。
日記投稿画面は、以下のようになります。
第7回へつづく!
今回の記事では、Django テンプレートに、様々な工夫を施しました。
今回の記事のポイントは、以下の4つです。
- Django テンプレート言語の代表的な機能として「変数」と「タグ」がある
- テンプレートの継承を利用すれば、テンプレートの作成が楽に!
- class 属性を追加するには、form クラスを扱う方法と django-widget-tweak を利用する方法がある
- django-bootstrap を利用することで、Django アプリとして bootstrap を利用することができる
次回は、Django アプリのテストの実装方法を学びます。
次回もお楽しみに!
第7回はこちら!
こちらの記事もオススメ!
2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
2020.07.30Python 特集実装編※最新記事順Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた!P...
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
「好きを仕事にするエンジニア集団」の(株)ライトコードです! ライトコードは、福岡、東京、大阪、名古屋の4拠点で事業展開するIT企業です。 現在は、国内を代表する大手IT企業を取引先にもち、ITシステムの受託事業が中心。 いずれも直取引で、月間PV数1億を超えるWebサービスのシステム開発・運営、インフラの構築・運用に携わっています。 システム開発依頼・お見積もり大歓迎! また、現在「WEBエンジニア」「モバイルエンジニア」「営業」「WEBデザイナー」を積極採用中です! インターンや新卒採用も行っております。 以下よりご応募をお待ちしております! https://rightcode.co.jp/recruit