[Python]とにかくわかりやすく！djangoでアプリ開発！ーその１ー

#はじめに

昔にdjangogirlチュートリアルなど読みながらアプリを作ったこともありましたが、最終的に**結局どういう仕組みで動いているのかわからなかった**ということがありました。

多分それは、当時ファイルの名前の意味や、書いてある関数の意味など、よくわからず、見よう見まねにやっていたからだと思います。
※最初は写経だけでも十分ですし、それで何かを作るということがとても重要でした。

またpythonのwebフレームワークに関しては、まだまだ日本にはちゃんと解説された書籍は無く、なかなか学びづらいとこもあったのかなと思っています。

#本記事の目的

python初心者の方が、本記事を見たあとに、一人でアプリ開発できることを目的にしております。
※インストールや開発環境については記載しません


#環境

macOSX　Sierra
python3.7
django 2.1.5

#djangoとは

pythonのwebフレームワークです。フレームワークとは、開発するための機能や仕組みが丸っと準備されている物のことを言います。

アプリの設計としてMVC(model/view/control)モデルが存在しますが、djangoに関してはMTV（model/template/view）という考え方が用いられています。

参照：https://qiita.com/kotayanagi/items/01e9a617571e2b9526bc

#☆プロジェクトの立ち上げ
まずは作業するディレクトリを準備します。
適当にデスクトップにしておきます。

```terminal
$ cd Desktop
```

デスクトップにプロジェクトを立ち上げます

```terminal
$ django-admin startproject myapp
```

これで以下のような階層ができたと思います。
myappのフォルダの下に、myappとmanage.pyが作成されています。
それぞれの説明をつけておきます。

```terminal
$ tree myapp
myapp　
├── manage.py　#(ざっくり)機能に関するファイル　　　　　　　　　　　　　　　　　　　
└── myapp #このプロジェクトで使うファイルがまとめらているフォルダ
    ├── __init__.py #初期化処理を行うファイル
    ├── settings.py #設定情報を記述するファイル
    ├── urls.py #URLを管理するファイル
    └── wsgi.py　#メインプログラムのファイル
```

ここまでできたら、一旦サーバーが起動するか確認します。
myappディレクトリに移動します。(manage.pyがあるフォルダ)

```terminal
$ cd myapp
```
サーバー起動します。

```terminal
$ python manage.py runserver
```

ブラウザで127.0.0.1:8000にアクセスして、以下のように出ればOKです！
※ターミナルでctrl+Cでサーバー停止できます。
<img width="1195" alt="スクリーンショット 2019-02-02 12.09.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/241505/26ab20de-cf7b-09e2-0a17-da71842169c4.png">
※会社のwindowsのPCで同じことやったら、pathが環境変数設定のことでエラーが出ました。。


#改めて

考え方がとても大事なので、MVCアーキテクチャについて再度。

|      MVC 　 |       説明 |      MTV|
|:-----------------|:-----------------:|:-----------------:|
| Model             |アプリとDBを繋ぐ物 |Model|  
| View          | 画面表示/ページの作り |    Template|
| Controller          |  文字通りコントロールするもの |  View|

リクエストされたら、controlerがmodelを呼び出して、DBから必要なデータを受け取り、さらにviewを呼び出して、ベージを作ってレスポンスをするという流れです。

たとえば、会員番号を入力したら、自分の情報がDBが呼び出されて、マイページに表示されるというのと一緒です。

#☆アプリの作成

先ほどプロジェクトを立ち上げましたが、ここにはMVCの仕組みは存在しませんでした。
なので、ここにさらにアプリケーションを作成して、MVCの仕組みを導入します。

```
$ python manage.py startapp app1
```
app1というフォルダが作成されたとともに、sqliteのファイルも作成されました。

```terminal
$ tree myapp
myapp
├── app1
│   ├── __init__.py #初期化処理を行うもの
│   ├── admin.py #管理者ツールのためのもの
│   ├── apps.py　#アプリの処理
│   ├── migrations #DBに関する機能がまとまったファイル
│   │   └── __init__.py
│   ├── models.py　#modelに関するもの
│   ├── tests.py　#テストに関するもの
│   └── views.py　#表示に関するもの
├── db.sqlite3
├── manage.py
└── myapp
    ├── __init__.py
    ├── __pycache__ #キャッシュなので無視
    │   ├── __init__.cpython-36.pyc
    │   ├── settings.cpython-36.pyc
    │   ├── urls.cpython-36.pyc
    │   └── wsgi.cpython-36.pyc
    ├── settings.py
    ├── urls.py
    └── wsgi.py
```
このアプリ自体は、幾つでも増やすことができます。プロジェクトの中に、様々なアプリを作ることができるということです。

例えば顧客を管理するアプリ、商品を管理するアプリ、受注を管理するアプリ
のような感じです。

ちゃんとアプリが動くか確認をしたいので、適当にhelloworldでもやりたいと思います。
表示に関する「制御」のことはviewだったので、view.pyをいじります。

本来画面表示に関してはテンプレートをいじりますが、一旦そこまでやらずviewで完結させます。

大事なのは、HttpResponseを使うところです。
aisatsuという関数を作って、「HttpResponseで情報(helloworld)を返して表示します。」という処理を書いておきます。

```python:views.py
from django.shortcuts import render
from django.http import HttpResponse

def aisatsu(request):
    return HttpResponse("Hello World")
```

これで画面表示の準備はできたので、次は画面を表示するためのURLを準備しておきます。
つまり特定のアドレスにアクセスしたら、aisatsu関数が実行されるにしなきゃいけないということです。
URLはurls.pyのurlpatternsにまとめられています。

```python:urls.py
from django.urls import path
from django.contrib import admin
import app1.views as app1

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app1/', app1.aisatsu),
]
```

最初にapp1フォルダのviews.pyを呼び出せるようにimportし、app1と名付けます。
そして、urlpatternsにapp1というurlを作成し、aisatsu関数の処理を呼び出しました。
※url関数もあります。
※url関数ではURLの書き方は正規表現を用いています。こちらhttps://qiita.com/hiroyuki_mrp/items/29e87bf5fe46de62983cを参照に。

ちゃんと動いているか確認します。

```terminal
$ python manage.py runserver
```

ブラウザで127.0.0.1:8000/app1/にアクセスして、helloworldが出ればOKです！
<img width="541" alt="スクリーンショット 2019-02-02 13.48.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/241505/6e9bca4e-e32f-bd71-360c-3271d68eae2e.png">

#☆ちょっとだけ改善を行います。

現状だと、app1の処理を実行を、myappのurls.pyで管理しています。
つまりapp1に処理を増やすたびに、urls.pyに修正を加えなくてはいけないんです。しかもアプリをどんどん増やしていけば、それだけ複雑な管理が必要です。不便です。

ということでアプリ内でアプリのURLの管理を完結できるようにします。

**app1フォルダ内に**、urls.pyを**作成します**
書き方は同じです。nameという引数を使ってurlに名前をつけています。nameは次の投稿で生きてきます。

```python:app1/urls.py
from django.conf.urls import url
from django.urls import path
from . import views

urlpatterns = [
    path("",views.aisatsu,name="aisatsu")　#空のテキストを指定
]
```
myappのurls.pyは以下のよう変更し直します。
include関数は、引数のモジュールを読み込むためのものです。今回はapp1フォルダのurls.pyを読み込み、app1/のURLを割り当てるようにします。

```python:myapp/urls.py
from django.urls import path,include
from django.contrib import admin

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app1/', include('app1.urls')),     #ここが肝！
]
```
今後アプリのURLの割り当ては、myappではなくapp1内のurls.pyでできるようになりました。

#クエリパラメタの設定

ここでなぜクエリパラメタの話がいるのか、それはhttpメソッドについて知ることが大事だからです。（簡単ですが）※上記ではしれっとHttpresponseを使いました。

クエリパラメタとは
`https://www.amazon.co.jp/ref=br_msw_pdt-2　?　_encoding=UTF8&smid=A3BXOMJQF0Y34H&...`
この「?」以降に続く、「=」で結ばれたもののことです。

分かりやすくするために、app1内のviews.pyを書き換えてみます。

```python:views.py
from django.shortcuts import render
from django.http import HttpResponse

def aisatsu(request):
    name = request.GET['name']
    return HttpResponse('My name is '+ name +'.')
```

これでブラウザで
http://127.0.0.1:8000/app1/?name=hiroyuki
と入力すると
<img width="523" alt="スクリーンショット 2019-02-02 16.00.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/241505/cbffeef1-6478-45d7-baa6-3cf1caa7f51f.png">

requestというのは、HttpRequestというクライアントのアクセスを管理するclassのインスタンスで、GETというメソッドを持っています。クエリパラメタに記入されたものはここに保管されています。

ついでにパラメタがなかった場合に備えます。
if文で、リクエストの中にクエリパラメタがあるかないかで処理を分岐させます。

```python:views.py
from django.shortcuts import render
from django.http import HttpResponse

def aisatsu(request):
    if 'name' in request.GET:
        name = request.GET['name']
        result = 'My name is '+ name +'.'
    else:
        result = 'please enter your name at url bar!'
    return HttpResponse(result)
```

まとめると
リクエスト：クライアント**からの**アクセスを管理。
レスポンス：クライアント**への**アクセスを管理。

urlpatternをいじれば、呪文みたいではない見やすいURLに変更することができますが、今回は割愛します。


#この記事はここまで

続きはこちら→[とにかくわかりやすく！Djangoでアプリ開発！ーその２ー](https://qiita.com/hiroyuki_mrp/items/18c790034afe83541160)

#p.s.
一時期mezzanineというCMSを使っていたのですが、django1.11が必要らしく、django2を使っていませんでした。