DjangoでAPI呼び出し

djangoからAPIで他のサービスを呼び出してみます。この例では[OpenWeatherMap](https://openweathermap.org/)を使って任意の都市の天気予報を取得してみます

#1. Django環境を用意します
- [Django Girls Tutorial](https://djangogirlsjapan.gitbooks.io/workshop_tutorialjp/content/)、[Djangoを使ってみる](https://qiita.com/egplnt/items/9620e1948fedcc052585)等を参照し、Django環境を用意します

#2. アプリを用意します
- `python manage.py startapp アプリ名`でアプリを用意します。ここではサンプルとして`rest`というアプリを作成しています
- 上記で作成したアプリを`プロジェクト名/urls.py`に登録します

```python:project/urls.py
urlpatterns = [
    path('admin/', admin.site.urls),
    path('rest/', include('rest.urls')),    
]

```

- `アプリ名/urls.py`に作成する画面に応じてアプリ名/urls.pyに登録します。ここではアプリの初期画面（`rest/`）として`index.html`を表示し、そこから送付した問い合わせに応じて`rest/forecast`というパスで`forecast.html`が表示されることにします

```python:app/urls.py
urlpatterns = [
    path('', views.rest, name='rest'),
    path('forecast', views.forecast, name='forecast'),    
]
```


#3. viewsにAPI呼び出しメソッドを記述します
-[OpenWeatherMap](https://openweathermap.org/)へサインアップ（無料）して32桁のAPIキーを取得します

```python:views.py

from django.shortcuts import render
import requests

def rest(request):
    print("rest entered")
    return render(request, 'rest/index.html')

def forecast(request):
    print("forecast entered")
    API_Key = '32桁のOpenWeatherMapのAPIキーを入力'
    city = "Tokyo,jp"
    if request.POST['city']:
        city = request.POST['city']
    url = 'http://api.openweathermap.org/data/2.5/forecast'
    query = {
        'units': 'metric',
        'q': city,
        'cnt': '30',
        'appid': API_Key
    }
    r = requests.get(url, params=query)
    print("response", r.json())
    print("Weather forecast in Tokyo at UTC(needs +9h): ")
    result = []
    for x in range(r.json()['cnt']):
        print("x: ", x)
        result.append(r.json()['list'][x]['dt_txt'])
        result.append("temp: ")
        result.append(r.json()['list'][x]['main']['temp'])
        result.append("weather: ")
        result.append(r.json()['list'][x]['weather'][0]['main'])
        result.append("/")
        result.append(r.json()['list'][x]['weather'][0]['description'])
        result.append('\n')

        print(r.json()['list'][x]['dt_txt'],
        "temp: ", r.json()['list'][x]['main']['temp'],
        "weather: ", r.json()['list'][x]['weather'][0]['main'], "/", r.json()['list'][x]['weather'][0]['description'])

    mapped_num = map(str, result) #格納される数値を文字列にする
    result_string = ' '.join(mapped_num)
    print("result_string", result_string)
    print("city", city)
    return render(request, 'rest/forecast.html', {'city': city, 'result': result_string})
```


#4. templateを用意します
- 上記画面遷移に応じたhtmlファイルを用意します

```html:base.html
{% load static %}
<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{% static 'vendor/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'vendor/bootstrap/css/bootstrap-grid.min.css' %}" rel="stylesheet">
<script src="{% static 'vendor/jquery/jquery-3.2.1.min.js' %}"></script>
<script src="{% static 'vendor/bootstrap/js/bootstrap.min.js' %}"></script>
<link href="{% static 'app/search/search.css' %}" rel="stylesheet">
{% block extrahead %}{% endblock %}
</head>
<body>
  <nav class="navbar navbar-expand-lg navbar-dark bg-dark" style="margin-bottom: 1rem;">
    <a class="navbar-brand" href="/">Django Exercise</a>
    <div class="collapse navbar-collapse" id="navbarNav">
    </div>
  </nav>

  <div class="container">
    {% block content %}
      {{ content }}
    {% endblock %}
  </div>
</body>
</html>
```

```html:index.html
{% extends "rest/base.html" %}

{% block title %}REST Exercise{% endblock title %}

{% block content %}

<div class="row">
  <div class="col-sm-12 col-md-12">
    <div class="card">
      <div class="card-header">Target</div>
      <div class="card-body">
        <form action="{% url 'forecast' %}" method="POST" enctype="multipart/form-data">
          {% csrf_token %}
          <div class="form-group row">
            <label for="model" class="col-sm-1 col-form-label">City</label>
            <div class="col-sm-3">
              <input type="text" class="form-control sbc_field" name="city" placeholder="Tokyo,jp"/>
            </div>
            <button type="submit" class="btn btn-primary" name='action' value="save">問い合わせ</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</div>

{% endblock %}
```

```html:forecast.html
{% extends "rest/base.html" %}

{% block title %}REST Exercise{% endblock title %}

{% block content %}

<div class="row">
  <div class="col-sm-12 col-md-12">
    <div class="card">
      <div class="card-header">Target</div>
      <div class="card-body">
        <form action="{% url 'forecast' %}" method="POST" enctype="multipart/form-data">
          {% csrf_token %}
          <div class="form-group row">
            <label for="model" class="col-sm-1 col-form-label">City</label>
            <div class="col-sm-3">
              <input type="text" class="form-control sbc_field" name="city" placeholder="Tokyo,jp"/>
            </div>
            <button type="submit" class="btn btn-primary" name='action' value="save">問い合わせ</button>
          </div>
        </form>
      </div>
    </div>
  </div>
</div>

<div class="row">
  <div class="col-sm-12 col-md-12">
    <div class="card">
      <div class="row">
        <div class="col-sm-12 col-md-12">
          <div class="card">
            <div>
              <h2>{{ city }} の天気</h2>
            <p>{{ result|linebreaksbr  }}</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

{% endblock %}
```

#5. 稼働確認します
- `http://localhost:8000/rest`で初期画面へアクセスし、天気予報を知りたい都市名を`都市名,国名`(例：`Tokyo,jp`、`New York,us`など）で入力し、「問い合わせ」ボタンでリクエストを送付します

<img width="1430" alt="スクリーンショット 2018-05-08 8.21.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/6a96e339-ce4b-53c5-5106-23fa50a9a9bd.png">

<img width="1409" alt="スクリーンショット 2018-05-08 8.21.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/125842/e2327b45-912d-87ce-52a7-0065127f7f98.png">


# 参考

- DjangoのREST化について - [Django REST Frameworkを使って爆速でAPIを実装する](https://qiita.com/kimihiro_n/items/86e0a9e619720e57ecd8)