Win10環境でDjango2のREST APIを試してみる

# 前提
Windows10にPythonやDjango2をインストールする記事はやたらあるので省略

最終的には**minishift上でDjango2のREST API**を試したくて試行錯誤してみます。
minishiftで作る前にDjango2のソースを作成しておきます。

- [Win10環境でDjango2のREST APIを試してみる](https://qiita.com/imp555sti/items/cbe579fbbfa3837075f3)
- [minishift V1.28.0でDjango2を動かす①：テンプレート確認](https://qiita.com/imp555sti/items/7fcb6d507c4e0eae5b3a)
- [minishift V1.28.0でDjango2を動かす②：テンプレート＆s2iソースの作成](https://qiita.com/imp555sti/items/728e774cd54e5781884b)
- [minishift V1.28.0でDjango2を動かす③：s2iソースの修正＆ビルド](https://qiita.com/imp555sti/items/f6ea232c1935f7c9042c)
- [minishift V1.28.0でDjango2を動かす④：残課題](https://qiita.com/imp555sti/items/ac7839d2a846f69a2bc1)
- [minishift V1.28.0でnginx+gunicorn+Django2を動かす](https://qiita.com/imp555sti/items/7733b48f41fc37ddda24)
- [minishift V1.28.0でnginx+gunicorn+Django2を動かす。あっcreatesuperuser忘れてた(笑)](https://qiita.com/imp555sti/items/e4ce4524fe8535313616)
- [openshiftに対応するためのDjango2コーディング時に気を付けるべき点](https://qiita.com/imp555sti/items/e9b37f0d5430220da690)


##環境
- Windows10
- Python3.7.2　Release Date: 2018-12-24　→　[Python.org](https://www.python.org/)
- Django2.1.4　Release Date: 2018-12-03　→　[django](https://www.djangoproject.com/)
- djangorestframework3.9.0　→　[Django REST framework](https://www.django-rest-framework.org/)
- eclipse OXYGEN　→　[Marge Doc Project](http://mergedoc.osdn.jp/)

##Django2のインストール

```shell
C:\Users\tak>pip --version
pip 18.1 from c:\python\python37\lib\site-packages\pip (python 3.7)

C:\Users\tak>pip install django==2.1.4
Collecting django==2.1.4
  Using cached https://files.pythonhosted.org/packages/fd/9a/0c028ea0fe4f5803dda1a7afabeed958d0c8b79b0fe762ffbf728db3b90d/Django-2.1.4-py3-none-any.whl
Collecting pytz (from django==2.1.4)
  Downloading https://files.pythonhosted.org/packages/f8/0e/2365ddc010afb3d79147f1dd544e5ee24bf4ece58ab99b16fbb465ce6dc0/pytz-2018.7-py2.py3-none-any.whl (506kB)
    100% |████████████████████████████████| 512kB 1.1MB/s
Installing collected packages: pytz, django
Successfully installed django-2.1.4 pytz-2018.7

```

同様に必要なモジュールをインストールしていきます。

```shell
C:\Users\tak>pip install djangorestframework
C:\Users\tak>pip install django-filter
:
```



# Local環境でDjango2の超簡単なREST APIを作成

eclipseを起動し新しいPyDev Djangoプロジェクト「smaple」を作成します。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/324255/9b6ef46a-9834-cd82-6f1b-db88842a8f82.png)

##APPを作成します。

```shell
c:\>cd rest\sample
c:\rest\sample>python manage.py startapp restapi
```

![02.png](https://qiita-image-store.s3.amazonaws.com/0/324255/f008b73d-44d9-0c4a-f250-844a46488a1b.png)


##自前のAPPを登録します。

```python:sample/setting.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',    # 追加
    'restapi',           # 追加
]
```

##TIMEZONEの設定を行います。

```python:sample/setting.py
# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'ja'       # 修正
TIME_ZONE = 'Asia/Tokyo'   # 修正
```

末尾にrest frameworkの設定を追加します。
まあ今回のには必要ないんですけどね(笑)

```python:sample/setting.py
# rest framework Internationalization
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}
```

##urlを登録します。

```python:sample/urls.py
"""sample URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from restapi import views                                      # 追加

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', views.current_time, name='current_time'),     # 追加
]
```

今回は簡単に現在時刻をJSON形式にするだけの簡単なものにしました。

```python:restapi/views.py
from datetime import datetime
from django.http import JsonResponse
from rest_framework import status
from rest_framework.decorators import api_view

# Create your views here.

@api_view(['GET'])
def current_time(request):
    ret = {'now':str(datetime.now())}
    return JsonResponse(ret, status=status.HTTP_200_OK)
```

テスト用コードを書きますが、ここも横着してリターンコード(`HTTP_200_OK`)の確認のみとしてます。

```python:restapi/test.py
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase

# Create your tests here.
class restapiTest(APITestCase):
    def test_current_time(self):
        url = reverse('current_time')
        response = self.client.get(url, '')

        self.assertEqual(response.status_code, status.HTTP_200_OK)
```

一応、`makemigrations` & `migrate`

```shell
c:\rest\sample>python manage.py makemigrations
No changes detected

c:\rest\sample>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying sessions.0001_initial... OK

```

でデバックモードで実行しブラウザで`http://127.0.0.1:8080/api/`にアクセスするとこんな感じでJSONが取得できます。

```json
{"now": "2018-12-26 14:00:29.432784"}
```

# 後から分かったこと(readinessProbe、livenessProbeへの対応)
目的はminishift上でDjango2を動かすことですので…
後で気が付きましたがminishift(openshift)でPodのヘルスチェックが仕込まれています。

その内容はURLのルートにアクセスして200_OKを返すかどうか。
よってURLルートにアクセスしてきた場合は空コンテンツを返すよう修正します。

```python:restapi/views.py
from datetime import datetime
from django.shortcuts import render
from django.http import JsonResponse, HttpResponse
from rest_framework import status
from rest_framework.decorators import api_view

# Create your views here.

@api_view(['GET'])
def current_time(request):
    ret = {'now':str(datetime.now())}
    return JsonResponse(ret, status=status.HTTP_200_OK)

def health(request):
    return HttpResponse('')
```

```python:sample/urls.py
"""sample URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from restapi import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', views.current_time, name='current_time'),
    path('', views.health, name='health'),         # ここを追加
]
```