DjangoとAPIを呼ぶの一歩目

環境
---
windows 8
Python 3.6.7
django 2.1.4

インストール済みか確認
---
pythonがインストール済みか確認

```
$ python --version
```

Djangoがインストール済みか確認

```
$ python
>> import djanog
>> django.get_version()
```

プロジェクトの立ち上げ
---

```
$ django-admin startproject {projectName}
```
{projectName} = myapp

```
$ cd myapp
```
myappディレクトリに移動

サーバー起動
---

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

アプリの作成
---
```
$ python manage.py startapp {appName}
```
{appName} = app1

```
myapp
├── manage.py
├── myapp
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   └── settings.cpython-36.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── app1
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── templates
    │   └── app1
    │       └── index.html
    ├── static
    │   └── app1
    │       ├── sunny.png
    │       ├── clouds.png
    │       └── rain.png
    ├── tests.py
    └── views.py
```
上図のように、ディレクトリ・ファイルを作成します。

API呼んで画面に表示するまで
---
※今回は [OpenWeatherMap](https://openweathermap.org/) のAPIを使用
![image.png](https://qiita-image-store.s3.amazonaws.com/0/331630/9610daaa-c620-3946-4a6f-1dd195f2cbae.png)

```python:myapp/settings.py
INSTALLED_APPS = [
    'app1', # 追記
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
```
アプリ名を追記する。

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

urlpatterns = [
    path('app1/', include('app1.urls')),
    path('admin/', admin.site.urls),
]
```
http://localhost:8000/app1/ にアクセスすると
`app1/urls.py`に行き...

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

urlpatterns = [
    path("", views.weather, name="weather"),
    path("form", views.form, name="form"),
]
```
`app1/views` の `weather関数` を実行する

```python:app1/views.py
from django.shortcuts import render

# Create your views here.
from django.http import HttpResponse
import requests
import json
from .forms import cityform

def weather(request):
    params = {
        'city': '',
        'msg':'How is the weather today?',
        'weather': '',
    }
    return render(request,'app1/index.html', params)

def form(request):
    if (request.POST['city']):
    
        city = request.POST['city']

        # call OpenWeatherMapAPI
        # APIキーの指定
        apikey = "{APIKey}"

        api = "http://api.openweathermap.org/data/2.5/weather?q={city}&APPID={key}"

        # 各都市の温度を取得する

        # APIのURLを得る
        url = api.format(city=city, key=apikey)
        # 実際にAPIにリクエストを送信して結果を取得する
        r = requests.get(url)
        # print(r)
        # 結果はJSON形式なのでデコードする
        data = json.loads(r.text)
        city = data["name"]
        weather = data["weather"][0]["description"]

        params = {
            'city': city,
            'msg': '',
            'weather': weather,
        }

    else:
        params = {
            'city': '',
            'msg': 'Select City!',
            'weather': '',
        }

    return render(request,'app1/index.html', params)
```
paramsに代入した値と共に、
`app1/templates/app1/index.html` に行き...

```html:app1/templates/app1/index.html
{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <title>How is the weather today?</title>
  </head>
  <body class="bg-secondary">

    <div class="text-center mb-5">
      <h1 class="mt-2">{{ city }}</h1>
      <h1>{{ msg }}</h1>
      <h1>{{ weather }}</h1>
      {% if 'sunny' in weather %}
        <img src="{% static 'app1/sunny.png' %}" style="height: 60px;"/>
      {% elif 'clouds' in weather %}
        <img src="{% static 'app1/clouds.png' %}" style="height: 60px;"/>
      {% elif 'rain' in weather %}
        <img src="{% static 'app1/rain.png' %}" style="height: 60px;"/>
      {% elif 'haze' in weather %}
        <img src="{% static 'app1/haze.png' %}" style="height: 60px;"/>
      {% endif %}
      <form action = "{% url 'form' %}" method = "post" class="mt-5">
          {% csrf_token %}
          <label for = "city" class="mr-1">Select City:</label>
          <!-- <input id = "city" type="text" name ="city" value="Tokyo,JP">
          {{ form.city_r.label }}： {{ form.city_r }} -->
          <select name="city" class="custom-select" style="width:140px;">
            <option value="">---</option>
            <option value="Tokyo,JP">Tokyo</option>
            <option value="London,UK">London</option>
            <option value="New York,US">New York</option>
          </select>
          <input type="submit" value="input" class="btn btn-outline-primary">
      </form>
    </div>
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </body>
</html>
```
※[Bootstrap](https://getbootstrap.com/docs/4.3/getting-started/introduction/) のStarter templateを使用

```index.html
<h1 class="mt-2">{{ city }}</h1>
      <h1>{{ msg }}</h1>
      <h1>{{ weather }}</h1>
```
先ほどのparamsの値が `{ city }`,`{ msg }`,`{ weather }` に代入されて...

![image.png](https://qiita-image-store.s3.amazonaws.com/0/331630/e0b6d1b6-2e28-0adf-33e3-9a56e8ff23e5.png)
上図が表示される。そして...
![image.png](https://qiita-image-store.s3.amazonaws.com/0/331630/da668a89-993e-b778-7f42-6e5ea053f323.png)
都市を選択して、ボタンを押すと...

```index.html
<form action= "{% url 'form' %}" method = "post" class="mt-5">
  {% csrf_token %}
  <label for = "city" class="mr-1">Select City:</label>
  <select name="city" class="custom-select" style="width:140px;">
    <option value="">---</option>
    <option value="Tokyo,JP">Tokyo</option>
    <option value="London,UK">London</option>
    <option value="New York,US">New York</option>
  </select>
  <input type="submit" value="input" class="btn btn-outline-primary"> 
</form>
```
`<form action= {% url 'form' %}` へ
`'form'` は...

```app1/urls.py
path("form", views.form, name="form"),
```
`name="form"`の `form` であり、

```python:views.py
def form(request):
    if (request.POST['city']):

        city = request.POST['city']

        # call OpenWeatherMapAPI
        # APIキーの指定
        apikey = "{APIKey}"

        api = "http://api.openweathermap.org/data/2.5/weather?q={city}&APPID={key}"

        # 各都市の温度を取得する

        # APIのURLを得る
        url = api.format(city=city, key=apikey)
        # 実際にAPIにリクエストを送信して結果を取得する
        r = requests.get(url)
        # print(r)
        # 結果はJSON形式なのでデコードする
        data = json.loads(r.text)
        city = data["name"]
        weather = data["weather"][0]["description"]

        params = {
            'city': city,
            'msg': '',
            'weather': weather,
        }

    else:
        params = {
            'city': '',
            'msg': 'Select City!',
            'weather': '',
        }

    return render(request,'app1/index.html', params)
```

`app1/views` の `form関数` が実行され...

```index.html
{% if 'sunny' in weather %}
  <img src="{% static 'app1/sunny.png' %}" style="height: 60px;"/>
{% elif 'clouds' in weather %}
  <img src="{% static 'app1/clouds.png' %}" style="height: 60px;"/>
{% elif 'rain' in weather %}
  <img src="{% static 'app1/rain.png' %}" style="height: 60px;"/>
{% elif 'haze' in weather %}
  <img src="{% static 'app1/haze.png' %}" style="height: 60px;"/>
{% endif %}
```
`params` の `weather`値によって分岐させ...
![image.png](https://qiita-image-store.s3.amazonaws.com/0/331630/47434002-af4c-5ada-8618-1fba96815824.png)
上図のように、今日の天気を教えてくれる。


参考
---
[【Python3】WebAPIを叩く【requests】](https://qiita.com/shunyooo/items/b408b8d61f9f73b21da7)
[[Python]とにかくわかりやすく！djangoでアプリ開発！ーその１ー](https://qiita.com/hiroyuki_mrp/items/8b2b78e066f35edbfbfd)
[【Django入門】画像などのstatic（静的）なファイルを使ってみよう](https://www.sejuku.net/blog/31179)