AzureのApp ServiceにDjango@Python3.6.4で作ったWebアプリをデプロイする

Xamarinでアプリを作っていて、連携するWebアプリを作る必要がありました。
前々からPythonをやってみたかったので、Azure+PythonでWebアプリにチャレンジしてみました。
初めてづくしでかなり苦労したので、忘れないうちに備忘録をつけておこうと思います。

この辺りの記事を参考にさせていただきました。
[Azure Web AppでPython3.6を動かす方法！！](https://qiita.com/ShikaTech/items/8217eded8bf757847b53)
[AzureにPython3.6/Django/PostgresのWebアプリをデプロイする](https://qiita.com/tag1216/items/0432f53e6b1a30dea912)

**今回作った環境はこんな感じ。**
>
マシン: MacBookPro（macOS 10.13.6）
Python: Anaconda(4.5.8)+Django(2.0.7)+Python(3.6.4)
開発環境: Visual Studio Code
Server: Azure App Service
DataBase: SQL Server

開発環境を何にするか悩んだ結果Anaconda→VSCodeに。
VSCodeを使うとAzureへのデプロイが簡単！便利！！

#初めてのPython
Macには初めからPython2系が入ってますが、当然最新の3系は入ってないのでインストールが必要。
インストール方法がたくさん有りすぎて困ってしまう。。。悩んだ結果、なんとなく便利そうな"Anaconda"を採用。
Macの場合すでにある2系と同率させるためにpyenvを使って仮想環境にインストールする方法もあるようですが、私が今後２系を使うことはないかなと思うのでそのままインストールしちゃいました。
仮想環境に入れると、それはそれで環境がぶつかったりして不具合起こることもあるみたいですしね。
[Anaconda を macOS にインストールする手順](https://weblabo.oscasierra.net/python-anaconda-install-macos/)
まあ、インストーラーなので何も考えずそのまま入れるだけです。

そして、大事なのは「Visual Studio Code」を入れること。これを使いたかったんです。

さて、これで環境は整いました。

#プロジェクトを作ってみる
## 環境を構築する
VSCodeは開発画面上でTerminalが使えるので、そこでプロジェクトを作ってみます。
ショートカットキーは「ctrl+shift+@」

####1.仮想環境を作ります
Azureで使えるPythonのバージョンは現在"3.6.4"が最新なので、そのバージョンで仮想環境を作ります。

```:Terminal
MacBook-Pro-2:~ username$ conda create -n <仮想環境名> python=<バージョン> <インストールするパッケージ名>
```

こんな感じ

```
MacBook-Pro-2:~ username$ conda create -n azure python=3.6.4
```

今回はAzureで使うことが目的でもあるのでパッケージは指定してません。
でもDjangoは使いたいのでDjangoをインストールします。あれ？もしかして、これ、パッケージ名にDjangoって入れればよかったのかな？
インストール完了。

<img width="397" alt="1_conda_list.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/e1fcd1b6-c6a4-e53a-5421-4ad4995b94b9.png">

####2.仮想環境ができたら環境を切り替えます

```:Terminal
MacBook-Pro-2:~ username$ source activate azure
```

みたいな感じ。これでazure用の環境に入ります。表示が"(azure) MacBook-Pro-2:~ username$"みたいに頭に(環境名)が入ってるのでわかりますね。

####3.必要なパッケージを追加します。
今回はDjangoとjinja2、AzureのDBと接続するためにdjango-pyodbc-azureを入れます。pyodbcはpythonでSQLServerを使えるようになるパッケージですよ。
あと、Django用のlintもインストールしておきます。これは入れておかないと文法エラーが出まくって大変です。

```:Terminal
・はじめにアップグレードしろって言われたのでアップグレード
(azure) MacBook-Pro-2:~ username$ pip install --upgrade pip
・Djangoをインストール
(azure) MacBook-Pro-2:~ username$ pip install Django
・Jinja2をインストール
(azure) MacBook-Pro-2:~ username$ pip install jinja2
・pyodbcをインストール
(azure) MacBook-Pro-2:~ username$ pip install django-pyodbc-azure
・django用のlintをインストール
(azure) MacBook-Pro-2:~ username$ pip install pylint-django
```

これで取り敢えずPythonの環境ができました。

##AzureにAppを作ります
すでにAzureのアカウントは持っているという前提で、Appを登録するところからやってみます。
DjangoのWebAppの作り方は公式サイトにもあるのですが、コードベースなので軟弱な私はGUIを使った方法を試してみました。

###1.リソースグループを作ります。
<img width="854" alt="2_resource.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/b0f8dc36-f4cf-a531-456f-f1861527e7bf.png">

メニューから「リソースグループ」を選び、「＋追加」で追加します。
リソースグループ名は適当にプロジェクト名なんか入れたらよいかと。

####2.アプリを追加します。
<img width="372" alt="3_addapp.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/17a2e417-a24a-427e-ee22-fff3eb0634cc.png">

1で作ったリソースグループを開いて「＋追加」ボタンをクリックします

<img width="914" alt="4_webapp+sql.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/dcd2f87b-99eb-1620-8bda-f1aaf189fd4a.png">

今回はデータベースも使用したいので「Web App + SQL」を選択します。
画面の指示に従ってアプリとDBを登録します。
**ここで登録したユーザー名とパスワードは忘れないようにメモしときましましょう。**

先ほど作ったリソースグループを見ると、"App Service"と"SQL Server"ができてることが確認できます。

<img width="743" alt="5_resource.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/98dfd17f-9872-8f6e-3cac-bb058ab37dc6.png">

####3.デプロイの準備をします。
CLIを立ち上げてコマンドを入力します

<img width="1395" alt="6_cli.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/3b520687-d873-49c8-2e6b-a752c3a23eef.png">

画面右上に「>_」ボタンがあるのでクリックすると、画面下にコマンドシェルが表示されます。
シェルの種類は「Bash」を選択しておきます。
下記の２つを実行します。

```:CloudShell
・デプロイユーザーを登録
az webapp deployment user set --user-name <username> --password <password>
・デプロイするアプリの登録
az webapp deployment source config-local-git --name <app_name> --resource-group <group_name>
```
デプロイの準備ができました。

####4.IPを登録する
ローカルからDBを使いたいとき、そのままだとファイアウォールに引っかかって接続できないので、アクセス許可するIPアドレスを登録しておきます。
SQL Server(歯車ついている方）を選択すると「ファイアウォール設定の表示」というリンクがあるので開きます。

<img width="648" alt="7_firewall.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/b1e4dd97-3642-5a5d-7173-ee773c5601f2.png">

IPが表示されているので、「＋クライアントIPの追加」をクリックするとリストに勝手に追加されちゃうので、そのまま保存。
ファイアウォールの設定が完了しました。

####5.App Serviceにpython3.6.4を追加する
アプリを開いて、開発ツールの拡張機能から入れたいバージョンを選択します。今回はPython 3.6.4。
<img width="487" alt="8_extension.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/db5e3e66-770b-ce3a-51b9-511be28b90f3.png">

リソースグループからApp Serviceを選んで、メニュー>開発ツール>拡張機能を選びます。
拡張機能ページを開いたら「＋追加」をクリックします。

<img width="691" alt="9_addversion.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/2337ed39-0b20-ac09-2352-7ac067242abc.png">

"Python 3.6.4 x64"を選択して「OK」します。

この辺りについては[こちらの公式ドキュメント](https://docs.microsoft.com/ja-jp/visualstudio/python/managing-python-on-azure-app-service)に詳しく書いてあります。

これで、サーバーの準備が整いました。多分。

##Visual Studio Codeの設定
####1.拡張プラグインを入れます。

<img width="348" alt="11_addpackage.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/a641af3d-d262-b6e4-ff61-18f30679f58c.png">

上記のアイコンをクリックすると、検索画面が表示されるので必要なパッケージを検索して追加します。
今回追加したのはこんな感じ。

* Django
+ Japanese Language Pack for Visual Studio Code
- Azure Extension Pack

AnacondaからインストールしたのでPython関連のはあらかじめ入ってたりします。

####2.Django用のLintをVSCodeに登録します。
メニューバーの「Code＞基本設定＞設定」を開き、右側のワークスペースタブを開いて下記のコードを追加します。

```
"python.linting.pylintArgs": [
    "--load-plugins=pylint_django"
],
```


##アプリをつくります
[この辺](https://docs.djangoproject.com/ja/2.0/intro/tutorial01/)とか。[この辺](https://eiry.bitbucket.io/index.html)を参考に作ってみました。
####1.アプリの作成
アプリを作成するディレクトリーに移動して、プロジェクトを作成します。プロジェクトができたらアプリを作ります。

```:Terminal
・環境を切り替えるのを忘れてはいけない
MacBook-Pro-2:~ username$ source activate azure

・プロジェクトを作る
(azure) MacBook-Pro-2:~ username$ cd <アプリを作りたいディレクトリ>
(azure) MacBook-Pro-2:~ username$ django-admin.py startproject <プロジェクト名>
・アプリを作る
(azure) MacBook-Pro-2:~ username$ cd <プロジェクト名>
(azure) MacBook-Pro-2:~ username$ python manage.py startapp <アプリ名>
```

<img width="588" alt="12_createapp.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/97a69639-2399-4112-6613-b81a51b58b84.png">


サンプルです。
ここまで作ったら、VSCodeの「フォルダーを開く」でプロジェクトのフォルダを開いてみましょー

<img width="354" alt="13_list.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/8d02f478-94cc-bd8e-73ac-132f3f769cba.png">


こんな感じにプロジェクトが作成されました。

上記のサイトを参考にDBを使ったアプリを作ります。

####2.設定ファイルを変更します。
まず、日本語と日本時間の設定をしておきます。

```python:settings.py
LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'
```

次にDBの設定。defaultの設定をodbc（AzureのDB）にします。

```python:settings.py
DATABASES = {
    'default': {
        'ENGINE': 'sql_server.pyodbc',
        'NAME': '<データベース名>',
        'USER': '<DBのユーザー名@SQL Server名>',
        'PASSWORD': '<DBのパスワード>',
        'HOST': '<サーバー名>',
        'PORT': '',

        'OPTIONS': {
            'driver': 'ODBC Driver 13 for SQL Server',
        },
    },
}
```

<サーバー名>はAzureポータルでデータベースを開くと基本情報に表示されています。ユーザー名とパスワードは先ほどDB作成時に登録したものです。
"USER"はユーザー名とSQL Serverの名前（サーバー名の最初の文字列）を@で繋ぎます。

####3.コードを書いていきます
前述のサイトなどを参考に、DBを使ったWebアプリを作ってみます。
上記以外は参考サイトの通りに作れば問題ないはず。
modelを作ったらDBを作成します。これも参考サイトに書いてある通りで大丈夫です。


```bash:Terminal
(azure) MacBook-Pro-2:~ username$ python manage.py makemigrations
(azure) MacBook-Pro-2:~ username$ python manage.py migrate
```


##サーバーにデプロイします
アプリが動いたらデプロイの準備をします。
Visual Studio Codeに「Azure Extension Pack」がインストールされていることを確認してください。

####1.setting.pyを修正します

```python:setting.py
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False # Falseにする

ALLOWED_HOSTS = ['*'] #'*'にする

STATIC_ROOT = 'static' #追加する
```
「DEBUG」を"False"に、「ALLOWED_HOSTS」を"['*']"にします。
「STATIC_ROOT = 'static'」を追加します。」

####2.デプロイ用のファイルを追加します。
サーバーに環境を作るための"requirements.txt"ファイルを作ります。manage.pyと同じ階層に置きます。

```python:requirements.txt
Django
jinja2
django-pyodbc-azure
```
####3.web用の設定ファイルを追加します。
まず、[こちらのサイト](https://docs.microsoft.com/ja-jp/azure/app-service/containers/quickstart-python)で紹介されているサンプルコードを取得します。

```:Terminal
git clone https://github.com/Azure-Samples/python-docs-hello-world
```

このサンプルコードにある"web.3.4.config"を"web.config"にリネームして、以下のように書き換えます。
manage.pyと同じ階層に置きます。

* "appSettings"の"WSGI_HANDLER"を"django.core.wsgi.get_wsgi_application()"にする
* "DJANGO_SETTINGS_MODULE"を追加する。プロジェクト名は先ほどアプリを作るときに作成した名前。上記の例だと"TestProject"
* "Python FastCGI"の"scriptProcessor"をpython3.6.4にする。

```xml:web.config
<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="WSGI_ALT_VIRTUALENV_HANDLER" value="main.app" />
    <add key="WSGI_ALT_VIRTUALENV_ACTIVATE_THIS"
         value="D:\home\site\wwwroot\env\Scripts\python.exe" />
    <add key="WSGI_HANDLER"
         value="django.core.wsgi.get_wsgi_application()" /> <!-- 変更する -->
    <add key="PYTHONPATH" value="D:\home\site\wwwroot" />
    <add key="DJANGO_SETTINGS_MODULE" value="<プロジェクト名>.settings" /> <!-- 追加する -->
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <handlers>
      <remove name="Python27_via_FastCGI" />
      <remove name="Python34_via_FastCGI" />
      <add name="Python FastCGI"
           path="handler.fcgi"
           verb="*"
           modules="FastCgiModule"
           scriptProcessor="D:\home\python364x64\python.exe|D:\home\python364x64\wfastcgi.py"
           resourceType="Unspecified"
           requireAccess="Script" /> <!-- 変更する -->
    </handlers>
    <rewrite>
      <rules>
        <rule name="Static Files" stopProcessing="true">
          <conditions>
            <add input="true" pattern="false" />
          </conditions>
        </rule>
        <rule name="Configure Python" stopProcessing="true">
          <match url="(.*)" ignoreCase="false" />
          <conditions>
            <add input="{REQUEST_URI}" pattern="^/static/.*" ignoreCase="true" negate="true" />
          </conditions>
          <action type="Rewrite" url="handler.fcgi/{R:1}" appendQueryString="true" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
```

####4.gitのローカルリポジトリを作ります
アクティビティバーのGitアイコンをクリックします。

<img width="348" alt="14_git.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/2a542900-3ec9-1363-418e-429d556a2313.png">

右上にあるアイコンをクリックすると、初期化するディレクトリを選べと言われるので、プロジェクトのディレクトリを選択して「リポジトリの初期化」をします。
これでgitのローカルリポジトリ完成です。

####5.デプロイします
<img width="354" alt="15_deploy1.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/ab73d455-9737-c288-c460-f2464173c771.png">
エクスプローラ画面でプロジェクトを右クリックするとメニューが表示されるので、「Deploy to Web App...」を選択します。
デプロイ可能なアプリが表示されるので、作っておいたアプリを選択します。

アジュールの拡張機能画面からもデプロイできます。
<img width="352" alt="16_deploy2.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/2563af86-6b32-ce57-4814-2e2a373a1714.png">
「APP SERVICE」にカーソルを持っていくとアイコンが出てくるので、こちらからデプロイします。

どちらからでもお好きな方で。

##AzureでWebアプリの設定をします。
Azureでデプロイしたアプリを選択します。
メニュー＞開発ツール＞コンソールでpythonの設定をします。
まずは"lsコマンド"でデプロイしたファイルがあることを確認しましょう。
初めは"D:\home\site\wwwroot"にいます。直下にデプロイしたプロジェクトファイルがあります。
そこで下記のコマンドを実行して、拡張機能をインストールしましょう。
初めにpipのアップグレードをしろとか言われるかもしれません。その時は素直にアップグレードしましょう。
<img width="512" alt="スクリーンショット 2018-07-23 21.53.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/129520/f64f20c1-e4d2-47e5-9743-e15160087402.png">


```bash:console
cd D:\home\python364x64
python.exe -m pip install --upgrade -r D:\home\site\wwwroot\requirements.txt
```

これでWebアプリが動くはず！！