Python Django チュートリアル(6)


勉強会用資料です
今回は本家のチュートリアルから完全にそれてbootstrapのことについて説明していきます．

[チュートリアルのチュートリアル](http://qiita.com/maisuto/items/d7e8cf0b5649f545ddb6)
[チュートリアル1](http://qiita.com/maisuto/items/d01e2cca63c8e5b2c18c)
[チュートリアル2](http://qiita.com/maisuto/items/357d13027e4fe5e10618)
[チュートリアル3](http://qiita.com/maisuto/items/eece9d880d94fd241a0d)
[チュートリアル4](http://qiita.com/maisuto/items/fef306bafc57f218794d)
[チュートリアル5](http://qiita.com/maisuto/items/33dfeb58f5953d1c5fdf)
→ [他のチュートリアル](http://qiita.com/maisuto/items/17653f344d1f64afa019)

[ソース（github）](https://github.com/usa-mimi/tutorial)


# Bootstrapを使おう

htmlのデザイン難しいですよね．
デザイナーがビシっと綺麗なhtmlを用意してくれたらいいですが，tutorialには残念ながらそんなもの望めません．
かと言って，綺麗なcssを素人が1から作っていくのは大変です．
そんなあなたにbootstrap！
bootstrapは無料（商用利用も可！）で使えるレスポンシブデザインのcss，javascript，font, iconなどを提供するフレームワークです．
> レスポンシブデザインはブラウザの大きさに合わせて自動的に表示幅や配置などを調整してくれるデザインのことです．
PC，スマートフォン，タブレットで同じhtmlを使い回すことができます．

[本家](http://getbootstrap.com/)
[とほほのBootstrap入門](http://www.tohoho-web.com/ex/bootstrap.html)
[Bootstrapとは？(wikipedia)](https://ja.wikipedia.org/wiki/Bootstrap)

djangoではbootstrapとの連携用のライブラリもありますし，cssやjavascriptの配置の練習にちょうどいいので
tutorialで扱っていきたいと思います．

## Bootstrapのdownloadと配置
ソース→`6ce33b05`

さっそく[本家](http://getbootstrap.com/)のページから一式をDownloadしてきましょう．

>![Kobito.2hc2qO.png](https://qiita-image-store.s3.amazonaws.com/0/58048/299a98f8-bb60-4786-8458-2d67e22439cc.png "Kobito.2hc2qO.png")

↓ Downloadボタンを押すと飛ばされます

>![Kobito.7n9C3e.png](https://qiita-image-store.s3.amazonaws.com/0/58048/9a349d18-bfe5-2aee-caae-36e46373ebba.png "Kobito.7n9C3e.png")

今回は一番左の **Bootstrap** を使います．
`bootstrap-3.3.6-dist.zip` というzipファイルがdownloadできると思います．これを解凍しましょう．

> ![Kobito.9C8A5v.png](https://qiita-image-store.s3.amazonaws.com/0/58048/0b195905-3089-9f17-a731-b334eedfaecd.png "Kobito.9C8A5v.png")
> 3.3.6はこんなファイル構成になっています．

次に，tutorialの`manage.py`と同じ階層に`static`というフォルダを作り，そこに解凍したbootstrapの中身を全部放り込みます．
移動後のファイル構成は以下のようになっているはずです．

```bash
(tutorial)$ tree .
├── db.sqlite3
├── manage.py
├── polls
│   ├── __init__.py
│   ├── ...
│   └── views.py
├── requirements.txt
├── static  # 今回追加したディレクトリ
│   ├── css
│   │   ├── bootstrap-theme.css
│   │   ├── bootstrap-theme.css.map
│   │   ├── bootstrap-theme.min.css
│   │   ├── bootstrap-theme.min.css.map
│   │   ├── bootstrap.css
│   │   ├── bootstrap.css.map
│   │   ├── bootstrap.min.css
│   │   └── bootstrap.min.css.map
│   ├── fonts
│   │   ├── glyphicons-halflings-regular.eot
│   │   ├── glyphicons-halflings-regular.svg
│   │   ├── glyphicons-halflings-regular.ttf
│   │   ├── glyphicons-halflings-regular.woff
│   │   └── glyphicons-halflings-regular.woff2
│   └── js
│       ├── bootstrap.js
│       ├── bootstrap.min.js
│       └── npm.js
└── tutorial
    ├── __init__.py
    ├──　...
    └── settings.py
```

## djangoの設定変更

ソース→`73d94740a`
[公式ドキュメント(英語)](https://docs.djangoproject.com/en/1.9/howto/static-files/)
[公式ドキュメント(日本語，ただしdjango1.4)](http://docs.djangoproject.jp/en/latest/howto/static-files.html)

チュートリアルで作ってきた http://localhost:8000/polls/ のようなページはDBの内容によって表示される内容が変わります．
このようなページ（URL）は動的なページ，動的ページ，動的コンテンツなどと呼ばれます．
それに対し，bootstrap.cssのようなcssやjsファイルは同じURLにアクセスすると常に同じ内容が返って来ます．
このようなページは静的なページ，静的コンテンツ，静的ファイルなどと呼ばれます．
動的コンテンツはアクセス毎に内容が変化するため，プログラム(pythonだったりrubyだったりphpだったり）を実行し，
ページ内容を変更する必要があります．
これに対して静的コンテンツは内容がかわらないため，アクセス毎に問い合わせをする必要がなく，
ブラウザなどに内容がキャッシュされます．
キャッシュすることにより，読み込みが高速化され，サーバの負荷が軽減されますが，内容の変更が反映されないなどのデメリットもあります．

djangoでは画像ファイル，cssファイル，javascriptファイルなどの静的ファイルは`static files`として管理し，
運用時に一箇所にまとめることで管理しやすくしています．
> 一箇所にまとめる方法は `$ ./manage.py collectstatic` ですが，runserver で実行している間はこのコマンドを使う必要はありません．
> deploy（サーバの設置）の説明もそのうちする予定なので，その時に詳しく説明します．

staticファイルは各アプリの下にある`static`ディレクトリの中がかき集められ，urls.pyにURLを追加することなく，
`http://localhost:8000/static/` でアクセスすることができます．
本チュートリアルでは取り扱う予定はありませんが，polls独自のcssが必要な場合は
`polls/static/polls/css/polls.css` のように設置し，
`http://localhost:8000/static/polls/css/polls.css` のようにアクセスします．
ちなみにdjango管理サイトようの静的ファイルは `django/contrib/admin/static/admin/`以下にあります．
> テンプレートの時も `polls/templates/polls/` のようになっています．
> `templates/polls/` や `static/polls/` のようにアプリ名を付けるのは冗長に感じるかもしれませんが，
> 名前衝突の回避や，コード的なメリットがありこのような構成になってるようです．


ただし，デフォルトで探索される`static`ディレクトリはアプリ（settings.pyの中のINSTALLED_APPS）の下にある
staticファイルのみです．
今回は`manage.py`と同じ階層に`static`ディレクトリを作成したため，このディレクトリも読み込ませるように設定を追加する必要があります．
静的ファイルが置かれているディレクトリを追加するには，`STATICFILES_DIRS`に追加したいディレクトリをタプル（or リスト）で指定します．

>![Kobito.1pM05v.png](https://qiita-image-store.s3.amazonaws.com/0/58048/e262d976-7a73-e0dc-7a7e-fe83a0136466.png "Kobito.1pM05v.png")
設定前は404になる．(諸事情で13000ポートで起動させてます）

```python:tutorial/settings.py
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)
```

>![Kobito.6wqhns.png](https://qiita-image-store.s3.amazonaws.com/0/58048/89437bd2-680e-9d08-e558-6fdc6e689d73.png "Kobito.6wqhns.png")
設定後はcssが取得できる．

## テンプレートの修正

ソース→`63cdd0cc`

template内から静的ファイルを読みこませるときは`{% static %}`というテンプレートタグを使います．
例えば`bootstrap.css`を読み込むときは
`<link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}" />`
のように書きます．
`{% static %}` タグを使うには最初に `{% load staticfiles %}` と書く必要があります．

手始めに一覧ページでbootstrap.cssを読み込ませてみます．

```html:polls/templates/polls/index.html
{% load staticfiles %}  <!-- ← 追加 -->
<html>
  <head> <!-- ← 追加 -->
    <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}" /> <!-- ← 追加 -->
  </head> <!-- ← 追加 -->
<body>
  <table border="1">
    <tr>
      <th>質問内容</th>
      <th>公開日</th>
      <th></th>
    </tr>
    {% for question in questions %}
    <tr>
      <td>{{ question.question_text }}</td>
      <td>{{ question.pub_date }}</td>
      <td><a href="{% url 'polls:detail' question.pk %}">詳細画面へ</a></td>
    </tr>
    {% endfor %}
  </table>
</body>
</html>
```

>![Kobito.mXJ2pb.png](https://qiita-image-store.s3.amazonaws.com/0/58048/25379da9-d62f-7403-9f3a-0749d1809d60.png "Kobito.mXJ2pb.png")
>before

>![Kobito.aIXL4h.png](https://qiita-image-store.s3.amazonaws.com/0/58048/1d77b9b4-0bf9-904c-87f9-c829012b7f36.png "Kobito.aIXL4h.png")
> after

なんかちっさくなっただけでcssの恩恵を感じませんね．
cssはhtmlのタグに`class`を指定することで真価を発揮します．

とりあえず試しにテーブル用のcssを当ててみましょう．
[bootstrapのページ](http://getbootstrap.com/css/#tables)によれば，tableクラスをつければtable用のデザインがあたるようです．
ついでにstripedも当ててみます．

```html:polls/templates/polls/index.html
...
<body>
  <table border="1" class="table table-striped">
    <tr>
      <th>質問内容</th>
...
```        

> ![Kobito.RIiscq.png](https://qiita-image-store.s3.amazonaws.com/0/58048/ad332c00-5fdc-7e63-8185-903edbbe12f6.png "Kobito.RIiscq.png")

はい．このようにtableタグにclassを追加するだけで，簡単にそれっぽいデザインになりました．

# テンプレートの拡張

[公式ドキュメント(英語)](https://docs.djangoproject.com/en/1.9/ref/templates/language/)
[公式ドキュメント(日本語，ただしdjango1.4)](http://docs.djangoproject.jp/en/latest/topics/templates.html)

すでに使用しているテンプレートですが，継承してこそ真価を発揮します．
qiita, bootstrapドキュメント, djangoドキュメント，どこでもいいですが，どのサイトでも
ページを移動した時のヘッダやフッタは基本的に同じで，ページの中身だけが変化しているでしょう？
サイト内の統一性を考えれば当然ですが，同一サイト内では枠組みは同じで，一部分のみが変化します．
クラス汎用ビューを使ったときと同じように，ベースのテンプレートを作り，そのテンプレートを継承して
変化させたい部分だけをオーバーライドすることでコード量を減らし，変更に強いサイトを作ることができるようになります．

本節ではベースとなるテンプレートを作成し，チュートリアルで作成したテンプレートを置き換え，
簡単にbootstrapのデザインを適用させる準備をします．

## ベーステンプレートの作成
ソース→`741a853886`

何はともあれ，ベースとなるテンプレートを用意しましょう．
`static`ファイルの時もそうでしたが，templateの場合も`templates`ディレクトリを`manage.py`と同じ階層に用意し，
それをベースのテンプレート置き場とします．

> `dashboard` など，如何にもベースになり得そうなアプリがある場合はそこに置くのもありだと思います．

templateの場合も`static`の時と同じく，デフォルトではアプリの下にある`templates`ディレクトリしか見てくれません．
`static`の時と同じように`settings.py`を変更しましょう．
templateの場合は`TEMPLATES`の中の`DIRS`に追加したいディレクトリを記述します．

```python:tutorial/settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  # ←← ここの中身を追加
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
```

次に`templates`の中に`base.html`を作りましょう．
肝心の中身ですが，[bootstrapのstarter-template](http://getbootstrap.com/examples/starter-template/)を使うことにします．
中身の修正が必要ですが，とりあえず同じものをベタッと貼ってそれを`base.html`として保存しましょう．

### 継承の前準備とベースの修正

ソース→`2cca1ce20eb`

とりあえず見ながら修正するようにしたいので，
`polls/templates/polls/index.html`を`base.html`を継承するように修正しましょう．
やることは簡単で，頭に`{% extends "base.html" %}`と書くだけです．

```html:polls/templates/polls/index.html
{% extends "base.html" %}
{% load staticfiles %}
<html>
...
```

この状態で`http://localhost:8000/polls/` を見ると以下のようになっているはずです．
>![Kobito.VImUOU.png](https://qiita-image-store.s3.amazonaws.com/0/58048/e2f76fec-e559-88eb-fb8a-5c2a6e9864bd.png "Kobito.VImUOU.png")

はい，ぐちゃぐちゃですね．
cssのパスがちゃんとあたってないからこうなってます．


>![Kobito.PWaw7X.png](https://qiita-image-store.s3.amazonaws.com/0/58048/3d578b43-e783-161c-4204-7ec8b4ab2982.png "Kobito.PWaw7X.png")
>> とりあえずcssやjsのパスを直して表示させたのがこちら．
>> htmlの修正はdjangoとはあまり関係ないのでさっくり飛ばします．ソースで確認してください．

### 変更用blockの追加と上書き

ソース→`8a3fe39358`

やっと本筋です．
今画面に出ている「Bootstrap starter template」の部分に質問一覧を表示させるようにしてみましょう．
htmlの`<div class="container">`の中身がこの部分に相当するので，ここを消去し，
継承先で上書きできるようにします．

```html:templates/base.html(修正前)
    <div class="container">

      <div class="starter-template">
        <h1>Bootstrap starter template</h1>
        <p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
      </div>

    </div><!-- /.container -->
```
↓

```html:templates/base.html(修正後)
    <div class="container">
    {% block contents %}{% endblock %}
    </div><!-- /.container -->
```
中身をごっそり消して`{% block %}`タグを用意します．
名前はなんでもいいですが，ここでは`contents`としています．

続いて継承先のほうのテンプレートを修正します．

```html:polls/templates/polls/index.html(修正前)
{% extends "base.html" %}
{% load staticfiles %}
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}" />
  </head>
<body>
  <table border="1" class="table table-striped">
    <tr>
      <th>質問内容</th>
      <th>公開日</th>
      <th></th>
    </tr>
    {% for question in questions %}
    <tr>
      <td>{{ question.question_text }}</td>
      <td>{{ question.pub_date }}</td>
      <td><a href="{% url 'polls:detail' question.pk %}">詳細画面へ</a></td>
    </tr>
    {% endfor %}
  </table>
</body>
</html>
```

↓


```html:polls/templates/polls/index.html(修正後)
{% extends "base.html" %}

{% block contents %}
  <table border="1" class="table table-striped">
    <tr>
      <th>質問内容</th>
      <th>公開日</th>
      <th></th>
    </tr>
    {% for question in questions %}
    <tr>
      <td>{{ question.question_text }}</td>
      <td>{{ question.pub_date }}</td>
      <td><a href="{% url 'polls:detail' question.pk %}">詳細画面へ</a></td>
    </tr>
    {% endfor %}
  </table>
{% endblock contents %}
```

htmlタグ，headタグ，bodyタグは継承元(templates/base.html)で設定しているので必要ありません．
`<table>`タグの中身を`contents`内に配置したいので，
`{% block contents %}`を頭に，`{% endblock contents %}`を最後につけています．
`{% endblock %}`には引数は必要ありませんが，blockの中身が大きくなるとどの`block`を閉じたか分からなくなるので
`{% block %}`と`{% endblock %}`が離れている場合はなるべく書くようにしたほうがいいでしょう．

ちなみに`{% endblock content %}`のように`{% block contents %}`と名前が対になっていない場合はエラーになります．

さて，どうなったかブラウザで確認してみましょう．

![Kobito.OTzMq7.png](https://qiita-image-store.s3.amazonaws.com/0/58048/db45b818-2767-47d5-c667-79042ce79b20.png "Kobito.OTzMq7.png")

テーブルがヘッダにくっついちゃってますが，まぁ及第点ではないでしょうか．

### base.htmlの修正とpolls/base.htmlの追加

ソース→`e722778ee`

せっかくTOPページが出来たので `http://localhost:8000/`でアクセスできるように
`tutorial/urls.py`を編集しておきます．
と言っても，実際にTOPページ用のviewがあるわけではないのでとりあえず`polls/`と同じ内容にしておきます．
名前は`index`にしてますが，`top`や`home`など好みの名前をつけてください．

```python:tutorial/urls.py
from django.conf.urls import include, url
from django.contrib import admin

from polls.views import index  # ← 追加

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^polls/', include('polls.urls', namespace='polls')),
    url(r'^$', index, name='index'),  # ← 追加
]
```

で，`base.html`の文言やリンクを修正していきます．

```html:templates/base.html
    <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
		...
          <a class="navbar-brand" href="{% url 'index' %}">Tutorial</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="{% url 'polls:index' %}">polls</a></li>
            <li class=""><a href="{% url 'admin:index' %}">admin</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav>

```

ここでちょっと一工夫．`<div id="navbar">`内のpollsの`<li>`に`class="active"`がついています．
`active`がつくと，ヘッダが以下のようにハイライトされ，どこのページにいるかわかりやすくなります．
![Kobito.fUGtFd.png](https://qiita-image-store.s3.amazonaws.com/0/58048/5069754f-fea7-0e8d-8105-0eedf4fd7087.png "Kobito.fUGtFd.png")

polls内のtemplateでは常にactiveを付けたいですが，他のアプリの場合はハイライトさせたくありません．
そこでこの部分を{% block %}にし，書き換えれるようにします．

```html:templates/base.html
<li class="{% block nav_polls %}{% endblock %}"><a href="{% url 'polls:index' %}">polls</a></li>
```

ただし，このままでは`polls/templates/polls`内のテンプレート全てを変更しないといけなくなります．
そこで，`polls/templats/polls/base.html`を作成し，`polls/templats/polls`下のテンプレートでは
`polls/base.html`を継承するようにします．


```テンプレートの継承関係
base.html
   └ polls/base.html
       ├ polls/index.html
       ├ polls/detail.html
       └ polls/results.html
```

```html:polls/templates/polls/base.html
{% extends "base.html" %}

{% block nav_polls %}active{% endblock %}
```
> nav_pollsにactiveを付ける

```html:polls/templtes/polls/index.html
{% extends "polls/base.html" %}
```
> base.htmlではなくpolls/base.htmlを継承する

ついでに`detail.html`と`results.html`も継承するように変更しておきましょう．
直し方は`index.html`の時と同じく，一行目に`{% extends "polls/base.html" %}`をつけ，
中身を`{% block contents %}`で囲むだけです．


![Kobito.pxgSZ5.png](https://qiita-image-store.s3.amazonaws.com/0/58048/6a164190-6e3c-47ad-2553-2a71a95d99c1.png "Kobito.pxgSZ5.png")
> TOPページ

![Kobito.YlkGRA.png](https://qiita-image-store.s3.amazonaws.com/0/58048/b6f3e493-e632-357f-6cce-6ed35194c095.png "Kobito.YlkGRA.png")
> 選択ページ

![Kobito.VjLnSb.png](https://qiita-image-store.s3.amazonaws.com/0/58048/459b4cd7-aff0-aa7c-59e0-906253709035.png "Kobito.VjLnSb.png")
> 結果ページ

# Django Bootstrap

ここまではdjangoのtemplate機能を使って自分でbootstrapのcssを充てる作業だったので
あまり恩恵を感じなかったと思います．
本章ではdjangoのデザインを簡単に置き換えることができる`django-bootstrap`を紹介します．

https://github.com/dyve/django-bootstrap3
http://django-bootstrap3.readthedocs.org/en/latest/index.html

## 導入とFormの置き換え

ソース→`498065d9fff`
> ソースをcheckoutsして試す場合は `pip install -r requirements.txt` を実行してください．

pipで簡単に入ります．
> bootstrapのバージョンの関係で，名前は`django-bootstrap3`になります．
> "3"のつけ忘れに注意．

```bash
(tutorial)$ pip install django-bootstrap3
Collecting django-bootstrap3
  Downloading django-bootstrap3-6.2.2.tar.gz
Building wheels for collected packages: django-bootstrap3
  Running setup.py bdist_wheel for django-bootstrap3 ... done
...  
  
Successfully built django-bootstrap3
Installing collected packages: django-bootstrap3
Successfully installed django-bootstrap3-6.2.2
```

次に`tutorial/settings.py`を開き，INSTALLED_APPSに`bootstrap3`を追加します．

```python:tutorial/settings.py
INSTALLED_APPS = (
    'django.contrib.admin',
...
    'django.contrib.staticfiles',
    'bootstrap3',  # ← 追加
    'polls',
)
```

インストール作業はこれで終わりです．
さっそくFormを書き換えてみましょう．
今回は`polls/templates/polls/detail.html`で出力しているformを書き換えてみます．

`{{ form }}`でformを出力する代わりに，`{% bootstrap_form %}`テンプレートタグを使ってformを出力させます．
使用前に`bootstrap3`をloadしておく必要があります．

```html:polls/templates/polls/detail.html
{% extends "polls/base.html" %}
{% load bootstrap3 %}  <!-- ← 追加 -->

{% block contents %}
<h1>{{ question.question_text }}</h1>

<form action="" method="post">
  {% csrf_token %}
  {% bootstrap_form form %} <!-- ← 修正 -->
  <input type="submit" value="Vote" />
</form>
{% endblock contents %}
```

1行の追加，1行の修正です．
画面上でどうなったか確認してみましょう．

![Kobito.EUxhO5.png](https://qiita-image-store.s3.amazonaws.com/0/58048/4604a78f-d0fc-3585-cc40-351f0a36cc13.png "Kobito.EUxhO5.png")

無駄についてた黒ポチが消えました．
なにも選択せずに`Vote`ボタンを押してみてください．

![Kobito.d0ide3.png](https://qiita-image-store.s3.amazonaws.com/0/58048/65446a19-cb4c-8c48-1c37-bdfb49a8b32d.png "Kobito.d0ide3.png")

こんな感じで，「いかにも」なエラーチェックが自動で付きます．

![Kobito.0QI9Rr.png](https://qiita-image-store.s3.amazonaws.com/0/58048/2200af04-97e1-4e3e-dadd-fb50e6aa3aea.png "Kobito.0QI9Rr.png")

選択肢にない値を送信するとこんな感じになります．

## builtin設定

ソース→`1f19af40`

さて，たった2行書くだけでFormが見違えるように綺麗になりました．
が，いちいち`{% load bootstrap3 %}` を書くには面倒くさいですよね．
`bootstrap3`用のテンプレートタグを自動で読み込むように`settings.py`に記述しましょう．

```python:tutorial/settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
            'builtins': [
                'bootstrap3.templatetags.bootstrap3',  # ←←← これを追加
            ],
        },
    },
]
```

ちなみに，ここに書けるのは`django1.9`からです．
`django1.8`以前は `django.template.base.add_to_builtins` メソッドを使うことで同じことができます．
`{% load %}`タグの時は`bootstrap3`だけでしたが，builtinsで指定する場合は`bootstrap3.templatetags.bootstrap3`
のように`templatetags`までのPATHも含めないと行けないので注意してください．

`polls/templates/polls/detail.html`から`load`の記述を消してエラーが出ないことを確かめましょう．

## message表示

ソース→`a2d08a455`

今は選択肢を選んでVoteすると結果ページに飛ぶだけの味気ないものになっています．
結果ページにユーザが何を投票したのか出力してみましょう．

[djangoドキュメント（英語）](https://docs.djangoproject.com/en/1.9/ref/contrib/messages/)
[djangoドキュメント（日本語）](http://docs.djangoproject.jp/en/latest/ref/contrib/messages.html)

djangoでは，次のページへなんらかの情報を持ちまわる仕組みを`messages`として提供しています．
使用するにはsettings.pyのINSTALLED_APPSに`django.contrib.messages`が含まれてる必要があります．
> adminなどと同じようにデフォルトで入ってるのでsettingsの修正は必要ないです．

まずはメッセージを追加しましょう．
今回は投票した時に，どの選択をしたかを出したいので，`polls/views.py`の`form_valid`を編集します．
メッセージの追加方法は `messages.success`関数に`request`と表示したいメッセージを渡すだけです．
> `success`の他に，`debug`，`info`，`warning`，`error`があります．


```python:polls/views.py
from django.contrib import messages
...

class Detail(SingleObjectMixin, FormView):
...
    def form_valid(self, form):
        form.vote()
        choice = form.cleaned_data['choice']
        messages.success(self.request, '"%s"に投票しました' % choice)
        return super().form_valid(form)
```        
> voteの戻り値でメッセージ（もしくはchoiceのインスタンス）を返すようにするともう少しスムーズになります．

続いて表示です．
メッセージの表示は全部のページで行いたいので，`base.html`に追加します．
`django-bootstrap3`ではメッセージの表示もサポートしているので，これも簡単にかけます．


```html:templates/base.html
...
    <div class="container">
    {% if messages %}
    {% bootstrap_messages messages %}
    {% endif %}
    {% block contents %}{% endblock %}
    </div><!-- /.container -->
...
```

![Kobito.joC23A.png](https://qiita-image-store.s3.amazonaws.com/0/58048/84c4dd0e-094e-6899-66a0-f253da2bf9dc.png "Kobito.joC23A.png")

こんな感じで，メッセージが表示されるようになりました．
右側にある　x ボタンを押すとこのメッセージは消えます．

<hr>
次のチュートリアルではテストについて説明していきます（本家チュートリアル5相当です）
[次のチュートリアルへ](http://qiita.com/maisuto/items/cce169a2455b116e2f82)

→ [他のチュートリアル](http://qiita.com/maisuto/items/17653f344d1f64afa019)