「画像でゴミ分類！」アプリ作成日誌day4～Bootstrapでフロントエンドを整える～

# はじめに
「画像でゴミ分類！」アプリ作成日誌4日目の今日はBootstrapを使ってフロントエンドを整えていきたいと思います。

＜記事一覧＞

- [「画像でゴミ分類！」アプリ作成日誌day1～データセットの作成～](https://qiita.com/eycjur/items/7d8223b28758c7dfaaa0)
- [「画像でゴミ分類！」アプリ作成日誌day2～VGG16でFine-tuning～](https://qiita.com/eycjur/items/3e954cb70dc15f996c2d)
- [「画像でゴミ分類！」アプリ作成日誌day3～Djangoでwebアプリ化～](https://qiita.com/eycjur/items/9c618538177c82f7fdc3)
- [「画像でゴミ分類！」アプリ作成日誌day4～Bootstrapでフロントエンドを整える～](https://qiita.com/eycjur/items/7b58c28eb8b16e722b5d) ←イマココ
- [「画像でゴミ分類！」アプリ作成日誌day5～Bootstrapでフロントエンドを整える2～](https://qiita.com/eycjur/items/08808097acd625e00652)
- [「画像でゴミ分類！」アプリ作成日誌day6～ディレクトリ構成の修正～](https://qiita.com/eycjur/items/f436787c2d517af6cad6)
- [「画像でゴミ分類！」アプリ作成日誌day7～サイドバーのスライドメニュー化～](https://qiita.com/eycjur/items/009dca5866c3e9ad0dd6)
- [「画像でゴミ分類！」アプリ作成日誌day8～herokuデプロイ～](https://qiita.com/eycjur/items/ebfae5db5dd1cd8349ea)

# 前回までのあらすじ
前回までの記事では画像認識アプリを実装してDjangoに載せるところまでやりました。今回はフロントエンドを整えていこうと思います。

# 画像表示
まず、前回の課題として画像の表示ができていないという問題がありました。その対策を書いておきます。

そもそも、画像をどのように表示させるかというと、webページ上に画像を置いておいて、そのパスを指定することでHTML内で読むことができるようになっています。なので、いったんバックエンド側で画像を保存して、それをパスで指定してフロントエンドで読みこむ形で実装します。(JavascriptだとBlob URLでブラウザ内だけの仮想のリンクみたいなものを作成できるらしいけど、Djangoで似たようなことができるのかわからなかった)

## 前準備
画像を扱えるように設定を追加しておく必要があります。

```py:garbage_proj/setting.py
# TEMPLATESのcontext_processors内に次を追加
'django.template.context_processors.media',

# 末尾あたりに以下を追加
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
```

また、ルーティングが行えるようにurlsも変えておきます。

```py:garbage/urls.py
# urlpatterns = []のリストの後に以下を追加
 + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
```
このように設定しておくと、`garbege/media`にアクセスが来た時に`media(garbage,garbage_projと同列のディレクトリ)`を参照するように設定できます。すなわち、`<img src="./media/images/title.png">`のようにすることで、リンクがつながります。

# templateファイル
それではtemplateファイルを書いていきます。

```django:garbage/templates/garbage/index.html
{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>画像でゴミ分類！</title>
	<link rel="stylesheet" type="text/css" href="{% static 'garbage/css/bootstrap.css' %}" />
	<link rel="stylesheet" type="text/css" href="{% static 'garbage/css/style.css' %}" />
</head>
<body>
	<img src="./media/images/title.png" alt="画像でゴミ分類！" class="m-4" id="title">
	<div class="container row">
		<div class="col-lg-6 offset-lg-3 col-md-8 offset-md-2">
			<div class="container card p-4 mt-4">
				<p>分類を調べたい画像を入力してください</p>
				<form action="/garbage/result" method="post" enctype="multipart/form-data">
					{% csrf_token %}
					{{ form }}
					<br>
					<button type="submit" class="mt-3">送信</button>
				</form>
			</div>
		</div>
	</div>
	<h4>既存の画像を利用する</h4>
	<div class="container row">
		<div class="col-md-6 p-3">
			<img src="./media/images/temp1.jpg" alt="画像1" class="sample-img">
		</div>
		<div class="col-md-6 p-3">
			<img src="./media/images/temp2.jpg" alt="画像2" class="sample-img">
		</div>
	</div>
</body>
</html>
```
Bootstrapのグリッドシステムで簡単にレスポンシブに対応できるのがいいですね。
デザインの現物は以下のようになります。
![ps-1](https://github.com/eycjur/garbage/blob/master/qiita_image/ps-1.png?raw=true)

```django:garbage/templates/garbage/result.html
{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>画像でゴミ分類！</title>
	<link rel="stylesheet" type="text/css" href="{% static 'garbage/css/bootstrap.css' %}" />
	<link rel="stylesheet" type="text/css" href="{% static 'garbage/css/style.css' %}" />
</head>
<body>
	<img src="./media/images/title.png" alt="画像でゴミ分類！" class="m-4" id="title">
	<div class="container row">
		<div class="col-lg-8 offset-lg-2">
			<div class="container card p-3 my-4 px-5">
				<h2 class="m-3">分類結果</h2>
				<img src="./media/images/image.png" alt="画像" id="result-img">
				<div class="container">
					<table class="table">
						<tr><th>分類</th><td>確率</td></tr>
						{% for key, value in pred %}
						<tr><th>{{ key }}</th><td>{{ value }}%</td></tr>
						{% endfor %}
					</table>
					<a href="{% url "index" %}">Topへ戻る</a>
				</div>
			</div>
		</div>
	</div>

</body>
</html>
```

predにはそれぞれの分類とその確率がタプルのリストみたいな感じになっています。
これも以下のようになります。
![ps-2](https://github.com/eycjur/garbage/blob/master/qiita_image/ps-2.png?raw=true)

ちなみにCSSはこんな感じです。

```css:garbage/static/garbage/css/style.css
body{
	text-align: center;
	background-color: rgb(239, 239, 240);
}

#title{
	float: center;
	width: 50%;
}

#result-img{
	width: 100%;
	height: auto;
}

.sample-img{
	width: 90%;
}
```
主に画像の調整はCSSで書いていますが、それ以外は基本的にbootstrapに投げちゃってる感じです。

次回はサンプルでも動くようにviewをいじるかJavaScriptを書いていきたいと思います。

＜記事一覧＞

- [「画像でゴミ分類！」アプリ作成日誌day1～データセットの作成～](https://qiita.com/eycjur/items/7d8223b28758c7dfaaa0)
- [「画像でゴミ分類！」アプリ作成日誌day2～VGG16でFine-tuning～](https://qiita.com/eycjur/items/3e954cb70dc15f996c2d)
- [「画像でゴミ分類！」アプリ作成日誌day3～Djangoでwebアプリ化～](https://qiita.com/eycjur/items/9c618538177c82f7fdc3)
- [「画像でゴミ分類！」アプリ作成日誌day4～Bootstrapでフロントエンドを整える～](https://qiita.com/eycjur/items/7b58c28eb8b16e722b5d) ←イマココ
- [「画像でゴミ分類！」アプリ作成日誌day5～Bootstrapでフロントエンドを整える2～](https://qiita.com/eycjur/items/08808097acd625e00652)
- [「画像でゴミ分類！」アプリ作成日誌day6～ディレクトリ構成の修正～](https://qiita.com/eycjur/items/f436787c2d517af6cad6)
- [「画像でゴミ分類！」アプリ作成日誌day7～サイドバーのスライドメニュー化～](https://qiita.com/eycjur/items/009dca5866c3e9ad0dd6)
- [「画像でゴミ分類！」アプリ作成日誌day8～herokuデプロイ～](https://qiita.com/eycjur/items/ebfae5db5dd1cd8349ea)

# 参考文献

- [django画像アップロード機能を実装する方法](https://freeheroblog.com/upload-img/)