• トップ
  • ブログ一覧
  • 【第6回】Djangoで日記アプリを作ろう ~Djangoテンプレート言語編~
  • 【第6回】Djangoで日記アプリを作ろう ~Djangoテンプレート言語編~

    広告メディア事業部広告メディア事業部
    2021.06.14

    エンジニアになろう!

    【第6回】Djangoで日記アプリを作ろう ~Djangoテンプレート言語編~

    前回は、UpdateView と DeleteView を利用して、日記の編集画面と削除画面を作成しました。

    【第5回】Djangoで日記アプリを作ろう ~編集画面・削除画面編~2021.06.07【第5回】Djangoで日記アプリを作ろう ~編集画面・削除画面編~【第5回】Djangoで日記アプリを作ろう ~編集画面・削除画面編~前回は、ListView と DetailView...

    今回は、Django テンプレート言語を利用して、画面の装飾を工夫してみましょう。

    上記機能の作成を通して、以下の内容を新しく学んでいきます。

    1. Django テンプレート言語とは?
    2. テンプレートの継承
    3. widget を利用してフォームに class 属性を付与する方法
    4. django-widget-tweak の使い方
    5. django で bootstrap4 を利用する方法

    それではまず、Django テンプレート言語について学んでいきましょう!

    Djangoテンプレート言語とは

    Django テンプレートとは、Django において HTML を生成するための仕組みです。

    そして、Django テンプレート言語は、その HTML 生成を支援する言語です。

    この言語を利用することで、テンプレートの中に動的なコンテンツを、簡単に埋め込むことができます。

    実を言うと、この言語はこれまでの連載の中で、たくさん利用してます。

    HTML に、フォームを作成するための、 {{ form }} という記述を行なっていました。

    これがまさしく、テンプレート言語を用いた表現です。

    今回は、まず Django テンプレート言語の基本概念である、「変数」と「タグ」を学びましょう。

    また、テンプレートの継承という概念を利用して、以下の2つをあげる取り組みをしていきましょう。

    1. これまで作成したテンプレートの可読性
    2. 作成効率

    変数

    Django テンプレート言語では、 {{ }} という表現は、変数と呼ばれます。

    主にビューで処理したデータを、テンプレート内部で利用するために使います。

    これまで、CreateView や DetailView を用いて、日記の作成画面や詳細画面を作ってきました。

    それらビューは、フォームや日記詳細データを、form や diary といった変数に与えます。

    Django テンプレート言語では、それら変数を {{ }} という形で呼び出し、テンプレート内部で利用することができるわけです。

    タグ

    テンプレート言語では、もう一つ代表的な表現があります。

    それがタグと呼ばれるもので、 {% %}  というように表現されます。

    主にタグは、Django  テンプレートが用意する、組み込み機能を利用する場合に利用されます。

    例えば、 {% now "Y年m月d日" %} というタグは、現在時刻を Y 年 m 月 d 日 形式で、HTML 上に表示します。

    このような便利な組み込みタグがあるので、動的なコンテンツでも簡単なものであれば、ビューで実装する必要性はありません。

    次の章では、「block タグ」と「extends タグ」を利用して、テンプレートの継承という操作を行なっていきましょう。

    テンプレートの継承とは

    テンプレートの継承とは、まず画面レイアウトの雛形となる「親テンプレート」を作り、その親テンプレートに各画面独自のコンテンツを加えてテンプレートを作成していくことです。

    Web ページは、大きく分けると、以下の3つで構成されています。

    1. ヘッダー
    2. ボディ
    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 属性を付与します。

    1. date
    2. title
    3. 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 デベロッパーツールで、日記投稿画面の実装を確認すると、以下のようになっているはずです。

    Chromeデベロッパーツールで日記投稿画面を確認

    これでフォームに、class を設定することができました。

    widget は、class を追加するだけでなく、フォームの大きさを変えたりフォームの種類を変えたりなど、フォームに関する様々な調整が可能です。

    例えば、title のウィジェットを TextInput から Textarea に変更すると、以下のように html のテキストエリアが作成されます。

    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 プロジェクトを起動してみましょう。

    日記投稿画面は、以下のようになります。

    Djangoプロジェクトの動作確認

    第7回へつづく!

    今回の記事では、Django テンプレートに、様々な工夫を施しました。

    今回の記事のポイントは、以下の4つです。

    1. Django テンプレート言語の代表的な機能として「変数」と「タグ」がある
    2. テンプレートの継承を利用すれば、テンプレートの作成が楽に!
    3. class 属性を追加するには、form クラスを扱う方法と django-widget-tweak を利用する方法がある
    4. django-bootstrap を利用することで、Django アプリとして bootstrap を利用することができる

    次回は、Django アプリのテストの実装方法を学びます。

    次回もお楽しみに!

    第7回はこちら!

    【第7回】Djangoで日記アプリを作ろう ~Djangoでテスト実施編~2021.08.30【第7回】Djangoで日記アプリを作ろう ~Djangoでテスト実施編~【第7回】Djangoで日記アプリを作ろう ~Djangoでテスト実施編~前回は、Django テンプレート言語につい...

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...
    featureImg2020.07.30Python 特集実装編※最新記事順Responder + Firestore でモダンかつサーバーレスなブログシステムを作ってみた!P...

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    広告メディア事業部

    広告メディア事業部

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background