DjangoでWEBアプリを作成する

###はじめに 
　Djangoで手軽にWEBアプリケーションを作成します。
パフォーマンスとか作業性とか色々気になるところですが、こんな便利なもの使わない手はありません。面倒なことはDjangoが行ってくれますので、アプリ開発にもっと集中できると思います。結構謎も多くて癖もあるようなのですが、簡単なアプリ作成を通じてDjangoのお面白さが伝われば嬉しいです。

###0.事前準備としてDjangoをインストールしておきます。
 私の作業環境OSは、Windows10 Proです。
 Djangoは、PythonとともにAnaconda(<https://www.python.jp/install/anaconda/index.html>)よりインストールしましたが、それぞれ別々にインストールしても良いと思います。
なお、今回はDjangoの簡易サーバーでアプリを動作させます。また、この記述の中でPythonとDjangoのバージョンは、次のとおりです。
  Python: 3.7.4
  Django: 2.2.5

AnacondaをインストールするとAnaconda PowerShell Promptが使用できるようになりますが、下記のコマンド操作でもこのPowerShellを使っておりとても便利です。以前はDosPromptベースでしたがAnacondaのアップデートでPowerShellへのサポートが行われました。

ここではAnacondaのインストール等の解説は省略しますが、今後本格運用を検討されるのであれば、WEBサーバ側のプログラムであるPython(とDjango)をどのような環境で動作させるのかを考慮すべきでしょう。実はそのあたりは私自身も正解がつかめていないのですが、本格的な動作環境を準備する場合において、経験的にはLINUX OS上でAPACHE2(またはNgnix)＋MYSQL(またはPostgreSQL)の組み合わせで環境構築するのが常套的なのではないかと思います。
単にDjangoの習得だけであればAnacondaのみ利用することは十分アリだと思います。アリーマイ・ラブです。

また、開発用のエディタは、Anacondaインストール時に Visual Studhio Code が選択可能となっているためこれを使って損はありません。私はとても便利だと思って使っています。
Visual Studhio Code は英語バージョンですが、日本語対応もしていますのでインストール後にカスタマイズしてください。
マイクロソフトはなんの得があってこんな便利のもの作っているのか不思議なのですが、その理由が社会貢献なのであればとても感謝です。

###1.projectの作成
作業環境が用意できたら、早速Django-adminコマンドでアプリケーションのベースとなるプロジェクトを作ります。(プロジェクト名は mysite としました。)

~~~
>> django-admin startproject mysite
~~~

###2.動作確認

~~~
>> cd mysite
mysite>> python manage.py runserver

Watching for file changes with StatReloader
Performing system checks...

System chck identified no issues (0 silenced).
December 02, 2019 - 14:33:50
Django version 2.2.5, using settings 'myproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
~~~

簡易サーバーが待機中になったところで、ブラウザを起動してアドレスに「127.0.0.1:8000」と入力して下記の画面表示されれば、Djangoは正常に動作しています。

![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440325/86ca3b0b-d8be-fe3d-08e8-64c9cb833928.jpeg)

たったこれだけの作業ですが、ここからアプリーションをカスタマイズしてゆきます。

###3.Appの作成
プロジェクトの中に自由にアプリ（業務の単位など）を作成していきます。
(作成するアプリ名は、items)
なお、簡易サーバーが待機中の場合は、[ctrl+C]でWEBサーバーを停止します。

~~~
mytite>> python manage.py startapp items
~~~

いま新しいアプリを作りました。ここでdjangoのファイル構成などを見てみましょう。
![キャプチャ1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440325/27f79a5a-028d-576a-9bbe-4476a7775e76.jpeg)

先程のコマンド[python manage.py startapp items]で【items】とその中身が作られました。
でもこの状態では、ファイルが準備されただけなので使えるように手を加えます。
しかしその前に、プロジェクトの設定を変更してはじめのロケット画面日本語表示できるようにします。

###4.プロジェクトの設定を変える。(settings.py)
これから【mysite】フォルダの直下にあるsettins.pyをイジっていくつかのことを行います。
ファイル構成などは、所謂”ベストプラクティス”的なものがあって、いろいろな紹介があるところなのですが、私の場合はあんまり構成を変えずにほぼ原型に近いまま使っています。
####ⅰ.ロケット画面の日本語表示
言語の変更を下記のようにします。初期値は 'en-us'だと思います。

~~~
LANGUAGE_CODE= 'ja'
~~~

ついでにタイムゾーンを下記のようにします。初期値は 'UTC'だと思います。

~~~
TIME_ZONE= "Asia/Tokyo"
~~~

この状態で簡易WEBサーバーを起動します．．．

~~~
mysite>> python manage.py runserver
~~~

![キャプチャ2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440325/26d33e69-0fd0-f7eb-f07d-efbc181eefb8.jpeg)

私が初めてこのロケット画面を見たときには、自分が打ち上げを成功させた様に思えてとても感動したことを覚えています。この画面わくわく感ありますよね。みなさんは感じましたか？
ロケットの下のところに、「DEBUG=Trueのが指定され．．．」と書かれていますが、settings.pyの初期値は、DEBUG = True　となっています。はじめのうちは、プログラムエラーとなってしまった場合の詳細などもわかりますのでこのままで良いと思います。
また、settings.pyの DEBUG = True の下辺りにホストのアドレスを記述する箇所がありますが、とりあえず下記のようにアスタリスクを入れて「なんでもよい」設定にしておきます。

~~~
ALLOWED_HOSTS= ['*']
~~~

もちろんローカルホストの場合はアスタリスクにかえて'127.0.0.1'でも動作します。

####ⅱ.App(items)の存在をプロジェクトに加える。
既にitemsアプリの準備をしましたがこのままだとただ関連するフォルダやファイルを作成しただけでプロジェクトに加えられておりません。私ははじめのうちは、この辺も自動で登録されれば良いのに、と思っておりましたが人が作ったものなのでそうならない理由があるのでしょう。
下記に示すのが、settings.pyの中にアプリを追加するための場所（INSTALLED_APPS）です。この中にitemsアプリも仲間に加えてもらいます。

~~~
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'items.apps.ItemsConfig', #<-追加する
]
~~~

追加した一行ですが、私は「itemsフォルダのapps.pyのなかのItemsConfigクラス」と云うふうに勝手な理解をしました。そしてそのファイルはこんな内容です。

~~~
from django.apps import AppConfig


class ItemsConfig(AppConfig):
    name = 'items'

~~~
続いてプロジェクトにitemsアプリのurl（アドレス）を教えてあげます。

###5.アプリにurl（アドレス）を設定する。
恐らくこのやり方は一つの解決法なのだと思いますが、一例的な手法だと思ってご理解下さい。

####ⅰ.プロジェクトの設定を変える。
プロジェクトフォルダの直下にある　urls.pyに変更を加えます。意味合いとしては「itemsアプリのurlを取り込むよ」といった感じです。この記述を受けて、itemsアプリにアプリ専用のurls.pyを作る必要が生じました。

~~~
from django.contrib import admin
from django.urls import path
from django.urls import include #<- 追加する

urlpatterns = [
    path('admin/', admin.site.urls),
    path('items/', include("items.urls")),  #<- 追加する
]

~~~

####ⅱ.アプリにurls.pyを新規作成する。
プロジェクトのurls.py取り込むべきitemsアプリのurls.pyを新規に作成します。
まずは、ファイル（urls.py）をitemsフォルダの直下に作成して下さい。
続いて下記の内容をそのファイルに記述します。

~~~
# -*- coding: utf-8 -*-
from django.urls import path
from . import views

app_name = 'items'

urlpatterns = [
]

~~~
これでurls.py親子の絆が繋がりました。上から三行目の記述ですが、同じ階層のviews.pyを参照シていることを意味します。今後views.pyに具体的な処理の記述をすることになります。その処理は関数化された処理であったり、クラス化された処理であったりしますが、その「処理」と「url(アドレス)」を関連付ける場所が下の方にあるurlpatternsです。このurlpatternsの中に処理の関連付けを加えてゆくのですが、「処理」はitemsアプリに関連したものが記述されのが自然ですから、itemsアプリ独自にurls.pyを持って「処理群」とてい記述をまとめてしまい、インデックス化したほうがプログラムの読みやすさが高まるのではないでしょうか。

~~~
from . import views
~~~

####ⅲ.views.pyに処理を記述してurl.pyに定義されたurl（アドレス）をつなげる。
ここが最後のバトンの渡し場所です。
ここでは三つのことを一度に行います。
・一つ目：処理（クラス）を記述する・・・views.pyに記述する
・二つ目：処理（クラス）の結果をhtmlページにするためのTemplateを用意する・・・index.htmlをさくせする
・三つ目：views.pyの処理（クラス）とurl(アドレス)をitemsアプリのurls.pyのなかで連結させる・・・urls.pyに記述する

まず始めに処理をviews.pyに記述します。

~~~
from django.shortcuts import render
from django.views.generic import TemplateView # <-追加する

#---------------------------------------------------------------
#htmlページに表示内容をクラスで作成する。
#---------------------------------------------------------------
class IndexView(TemplateView):
	template_name = "items/index.html"

	def get_context_data(self, **kwargs):
		context = super().get_context_data(**kwargs)
		context["opinion"] = "なんだこのやろう！　いらっしゃいませ！"
		return context

index = IndexView.as_view()
~~~

いろいろ突っ込みどころがありそうです。
まず今回はhtmlページに店員のあいさつを表示させる処理をしてますが、口の悪さは一つの愛情表現です。
ここではIndexViewクラスを定義しています。継承元はTemplateViewです。実は私はPython初心者なのですが、C#でプログラミング経験があるのでこの意味は理解できました。Djangoはいろんな汎用クラスを提供してくれています。そしてTemplateViewもその一つで、このクラスを継承するといろんな機能の恩恵を受けることができます。
get_context_data関数はその一つで、htmlページに渡す値をcontextを通してセットすることができます。頻繁に利用するので覚えておきたい関数です。
なんだか簡単に済ませてしまいましたが、TemplateViewクラスのget_context_data関数でcontext内にたくさん情報を詰め込んで、それをhtmlベージに渡しているだけのことです。

続いて、処理（クラス）の結果をhtmlページにするためのTemplateを用意します。Templateといってもhtmlファイルを用意するだけです。
まず、htmlファイルを入れいるフォルダを作成ます。itemsフォルダの直下にtemplatesフォルダを作成して下さい。そしてその中にアプリ名と同じフォルダを追加して、更にその中にindex.htmlを作成します。
少しややこしくなりましたので、先程追加したurls.pyとともに、今のファイル構成の状態を示します。

![キャプチャ3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440325/246933bd-32ae-e601-b9cd-49277c49d9f1.jpeg)

アプリ名のフォルダを経由させる理由は、本格WEBサーバーに移行したときの準備だと思って下さい。
views.pyのtemplate_name にクラスで使用するhtmlファイル入れていますが、アプリ名フォルダを経由させて記述しているのもそのためです。

~~~
template_name = "items/index.html"
~~~

さて、htmlはフロントエンドとしてユーザと対話させるために色んな装飾ができるのでしょうが、CSSやらJavaScriptやらが関係してきそうなので、ここはシンプルに表示させるだけにしたいと思います。
以下はindex.htmlの内容です。

~~~
<html>
	<head>
	</head>
	<body>
		<p>ビート店員のあいさつ：{{ opinion }}</p>
	</body>
</html>
~~~
{{ opinion }}の記述に注目して下さい。ここではviews.pyの中に定義したIndexViewクラスが吐き出すcontextの中にセットした発言を呼び出しています。
template(htmlファイル)内でDjangoの渡す値にアクセスするためには、{{ }}　で変数を囲みます。template内でJavaScriptを使用して変数として利用したい場合でも同じです。

~~~
context["opinion"] = "なんだこのやろう！　いらっしゃいませ！"
~~~

もしあいさつが足りないというときには、次のように回数を増やします。
views.pyの記述内容

~~~
class IndexView(TemplateView):
	template_name = "items/index.html"

	def get_context_data(self, **kwargs):
		context = super().get_context_data(**kwargs)
		opinion= [
			"なんだこのやろう！　いらっしゃいませ！",
			"なんだこのやろう！　いらっしゃいませ！",
			"なんだこのやろう！　いらっしゃいませ！",
			"なんだこのやろう！　いらっしゃいませ！",
			"コマネチッ！",
		]
		context["opinion"] = opinion
		return context

~~~


index.htmlの記述内容

~~~
<html>
	<head>
	</head>
	<body>
		<div>ビート店員のあいさつ：
			{% for bb in opinion %}
				<p>{{ bb }}</p>
			{% endfor %}
		</div>
	</body>
</html>
~~~
template(htmlファイル)内で制御系を使う時には、{% %}で制御文を囲うことが必要です。

最後に、views.pyの処理（クラス）とurl(アドレス)をitemsアプリのurls.pyのなかで連結させます。
作成したurls.pyのurlpatterns内に下記の一行を追加します。

~~~
# -*- coding: utf-8 -*-
from django.urls import path
from . import views

app_name = 'items'

urlpatterns = [
    path('', views.index, name='index'), #<-追加
]
~~~
path関数の初めの引数はurlです。ここでは127.0.0.1:8000/items/ でページが表示されるように引数なしです。127.0.0.1:8000/items/aaa　でページ表示させたい場合は、次のようにします。

~~~
path('aaa', views.index, name='index'), #<-追加
~~~
二つ目の引数は、views.py内のindexを示しています。

~~~
index = IndexView.as_view()
~~~
このやり方である必要はありませんが覚えておくと便利です。

三つ目の引数は逆引きするときに使います。例えばhtmlページからこの処理を呼び出すときなどにこの名前で呼び出します。

少し長くなりましたが漸くブラウザを起動して動作確認です。

簡易サーバーが起動していない場合は、下記のコマンドで待機状態にしておいて下さい。

~~~
mysite>> python manage.py runserver
~~~

ブラウザのアドレス欄に 127.0.0.1:8000/items と入力して下さい。
以下のようになれば、成功です。
![キャプチャ4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440325/c9dba82d-6a6b-e40f-ccf1-c24ee52dcf35.jpeg)

###6.今回のまとめ
いかがでしょうか、随分簡単にWEBアプリケーションを作ることができました。
Djangoの運用モデルは、MTVモデルだと言われていますが、今回の解説でT(Template)とV(View)を紹介しました。MTVモデルの考え方などについてもっと興味の有る方は、その権威を訪ねてしてググって下さい。
実務的には大抵の場合、開発は個人か限られた人員でおこなられると思います。TとVが別れていることは結構有り難くて、プログラマはサーバ側のプログラムに集中できて、デザイナはフロントエンドの見栄えに集中ができるのではないでしょうか。
後はM（Model）ですが、これは所謂データベースと関係があります。Djangoはデータベースを使ってこそ真骨頂を発揮するといっても良いと思いますが、その解説はまた次回にします。
(<https://qiita.com/cloghjordan/items/08caf9955d05e7bd127d>)

DjangoはフルスタックのWEBフレームワークといわれています。簡単に言うとDjangoはWEBアプリケーションを作成するための基本機能を全て備えているということらしいです。
なんだかとても可能性を感じさせますね。

ここまでのファイル構成を表示しておきます。
![キャプチャ5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440325/44b9fb6e-e6a1-9a57-2b79-795eb0ac31ec.jpeg)