Djangoを使ってRandomForestで作った分類モデルをWEBサービス化するまで(1)


python初心者で見よう見まねで色々やった内容の備忘録ですのでご了承ください。おかしな所があればご教授頂けると幸いです。

```環境
macOS High Sierra 10.13
Python 3.6.5
```

#背景
とある業務で入力した内容によってカテゴリを自動で分類するRandomForestで作ったモデルを作ったのではあるが、ターミナルレベルでしか動かせなかったので中々説明してもピンと分かってもらえなかったので、WEBサービスとして見える化しようと考えたことが発端です。


#環境構築
Djangoの開発環境を作っていきます。

```ターミナル
#Djangoのインストール
pip install django
#適当なディレクトリ配下にアプリを作っていきます
mkdir Django
cd Django
#プロジェクトを作成します
django-admin startproject mysite . #「mysite」部は任意の名前
#WEBアプリを作成します
python manage.py startapp demo #「demo」部は任意の名前
#ついでにjsやcssなどのファイルを置くディレクトリも作ります
mkdir static
#できたディレクトリなどを確認
tree -L 1 .
.
├── demo
├── db.sqlite3
├── manage.py
├── mysite
├── static
```

webサーバはwindowsのIISで立てたことがある程度の経験ですが、 「mysite」が「wwwroot」的なもので「demo」が各WEBサイトのファイルなどを置くディレクトリという感じで捉えています。

#基本設定
使う前にまず各種設定が必要になります。
設定は`mysite/settings.py`ファイルを修正します。
ここでは以下の3つの設定を行います。
1.アプリの追加
2.言語とタイムゾーンの変更
3.jsやcssファイルなどを置くディレクトリ設定
htmlはjsファイルやcssファイルは外部ファイルを参照することも多い思いますのでその設定です。

また、データベースの設定もこのタイミングで行うのが一般的そうですが、今回私はデータベースは使わないので割愛しました。

```mysite/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'demo', #demoアプリの追加
]

LANGUAGE_CODE = 'ja' #日本語に変更

TIME_ZONE = 'Asia/Tokyo' #日本に変更

USE_TZ = False #UTCタイムゾーンは使わない

#外部ファイルを置くディレクトリの場所などの設定を追加
STATIC_URL = '/static/' 

STATICFILES_DIRS = (
	[
		os.path.join(BASE_DIR,"static"),
	]
)
```


こちらのサイトが大変参考になりました
[Python + Djangoで外部CSS,JSを使用する][1]
[1]:https://qiita.com/t-iguchi/items/20dc31d5e004d7145634


#URL設定
次に作成した各アプリとURLを紐付けするためのルーティング設定を行います。エイリアス的な設定と捉えています。

```mysite/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('demo/', include('demo.urls', namespace='demo')), #追加
]
```

`'demo/'`はURLで言うと`localhost:8000/demo/`のdemoに当たる部分です。`localhost:8000/demo/`にアクセスがあったら`demo.urls`ファイルを参照してくださいということになります。namespaceはのところは記述しなくても良いらしいですが、指定して置くと冗長的にならない書き方ができるらしいので、ついでに指定するといいと思います。

次に先ほど指定した`demo.urls`の設定を行います。`urls.py`は初めは存在しないと思いますので下記のように作ってください。

```demo/urls.py
from django.conf.urls import url
from . import views

app_name = 'demo'
urlpatterns = [
	url(r'^index$', views.result),
]
```

端的に言うと`localhost:8000/demo/index`にアクセスしたら`views.py`の`def result(request):`の処理を実行しますということです。

では'views.py'を作成します。先ほど'demo/urls.py'で記述した通り、`def result(request)`に行いたい処理（例えばデータの受け渡しや加工など）を追記していきます。
今回は`demo/result.html`が開くようにしていきます。ついでに値の受け渡しも行います。


```demo/views.py 
from django.shortcuts import render

def result(request):
	hoge = "Hello World"
	hage = "GoodBye World"
	return render(request, 'demo/result.html',{'hoge': hoge, 'hage':hage})
```

`render`の部分は決まりごとのような形と思っています。値の受け渡しはカンマ区切りで複数渡すことも可能です。今回は`hoge`と`hage`の変数を`demo/result.html`に渡しています。

次に受け渡し先の`demo/result.html`を作成します。このファイルの置き場所はエイリアス配下に`templates/demo/`ディレクトリを作り設置するのが決まりのようですので、まずはディレクトリを作ります。

```ターミナル
#HTMLファイルを置くディレクトリを作成
mkdir demo/templates
mkdir demo/templates/demo/
```

そしてHTMLファイルを作ります。中身はただただ受け取った値を表示するだけのものです。

```demo/templates/demo/result.html
{% load static %}
<!doctype html>
<html>
<head>
	<script type='text/javascript' src="{% static 'js/jquery-1.8.0.min.js' %}"></script>
</head>
<body>
	<div>{{ hoge }}</div>
	<div>{{ hage }}</div>
</body>
</html>
```

1行目の`{% load static %}`で外部ファイルを置いてあるstaticディレクトリを読み込む宣言をしています。
このディレクトリのjsディレクトリに置いてあるjqueryファイルを`<script type='text/javascript' src="{% static 'js/jquery-1.8.0.min.js' %}"></script>`で読み込んで使っています。
先ほど`views.py`で渡した値は`{{ 変数名 }}`で受け取ることができます。

#動作確認

最後に動作確認を行います。
まずは、`python manage.py runserver`でサーバを立ち上げます。
そしてブラウザに`localhost:8000/demo/index`と入力するとWEBページが表示されるはずです。


![スクリーンショット 2018-08-30 11.46.13.png](https://qiita-image-store.s3.amazonaws.com/0/214322/24d849ac-14a2-89eb-0b80-4bb055c0b54a.png "スクリーンショット 2018-08-30 11.46.13.png")


今回は`localhost:8000/demo/index`を`result.html`と紐付けましたが、やはり名前は統一しておいた方が良かったなと思いました。


##参考サイト
[PythonのWebアプリケーション（Django）を初心者にもわかりやすく解説（１）【環境構築編】][2]
[2]:https://qiita.com/yoshizaki_kkgk/items/f3c79e38b802c7fc8863