Djangoで天気アプリを作成する方法
序章
この記事では、さまざまな都市の現在の天気を表示するDjangoアプリを作成します。
現在の気象データは、 Open Weather MapAPIによって提供されます。
データベースを操作してフォームを作成します。 このチュートリアルで学んだことは、後でより複雑なプロジェクトに適用できます。
前提条件
- このプロジェクトにはPythonがインストールされている必要があります。詳細については、このチュートリアルシリーズを参照できるはずです。
この記事のコードはPython3とDjango3.0で記述されているため、このチュートリアルに従うには、両方にある程度精通している必要があります。
ステップ1—プロジェクトの設定
Djangoのインストールは、他のPythonライブラリのインストールと似ています。
- 仮想環境を開始し、
pip
を実行してDjangoをインストールできます。 - または、プロジェクトディレクトリを作成し、
pipenv
を実行してから、pipenv
シェルをアクティブ化することもできます。
どちらの方法でも機能しますが、この記事ではpipenvを使用します。
注:別のDjangoインストール方法については、このチュートリアルシリーズを参照して追加情報を入手できるはずです。
公式ドキュメントには、HomebrewまたはLinuxbrewを使用してpipenv
をインストールする手順が記載されています。 pip
と一緒にpipenv
をインストールすることも可能です。
ターミナルで、環境ディレクトリを作成します。
- mkdir the_weather_env
次に、環境ディレクトリに移動します。
- cd the_weather_env
次に、pipenvを使用してDjangoをインストールします。
- pipenv install django
これにより、最新バージョンのDjangoがインストールされます。 この記事を書いている時点では、Djangoはバージョン3.0.5です。
この瞬間に、pipenvを使用して、後で使用するRequestsライブラリをインストールします。
- pipenv install requests
ターミナルで次のコマンドを実行して、プロジェクトのvirtualenvをアクティブにします。
- pipenv shell
これにより、新しいシェルサブプロセスが生成されます。
ステップ2—Djangoプロジェクトを開始する
Djangoをインストールしたら、まだ作成していない場合は、このプロジェクトのディレクトリを作成して移動します。
Djangoがプロジェクトを生成するために提供するstartproject
コマンドを実行できます。
- django-admin startproject the_weather
Djangoはあなたのディレクトリにいくつかの新しいファイルを作成しているはずです。
開発サーバーを起動してみましょう。 これを行うには、ターミナルの新しいディレクトリに移動します。
- cd the_weather
次に、manage.py
を使用して、ターミナルでrunserver
コマンドを実行します。
- python manage.py runserver
ターミナルを確認すると、アプリのURLが表示されます。 デフォルトでは、127.0.0.1:8000
になっているはずです。
次に、Webブラウザーを開き、そのURLにアクセスします。
「おめでとうございます」ページが表示された場合は、Djangoが正しく設定されていることがわかります。
ステップ3—管理ダッシュボードにログインする
次に、Djangoが提供する管理ダッシュボードにログインします。 これを実現するには、まずデータベースを移行する必要があります。つまり、Djangoはデフォルトのアプリに必要な事前定義されたテーブルを作成します。
まず、サーバーを停止する必要があります。 環境に応じて、これはキーボードコマンドCONTROL+C
またはCTRL+C
で実行できます。
次に、ターミナルでmigrate
コマンドを実行します。
- python manage.py migrate
そのコマンドを実行することにより、Djangoは設定のデフォルトデータベースであるSQLiteデータベースを作成し、そのデータベースにいくつかのテーブルを追加しました。 プロジェクトディレクトリに新しいdb.sqlite3
ファイルが表示されれば、データベースが作成されたかどうかがわかります。
Djangoが提供するテーブルの1つは、ユーザーテーブルです。これは、アプリ内のすべてのユーザーを格納するために使用されます。 作成しているアプリにはユーザーは必要ありませんが、管理者ユーザーがいると、管理ダッシュボードにアクセスできます。
管理者ユーザーを作成するには、ターミナルでcreatesuperuser
コマンドを実行します。
- python manage.py createsuperuser
管理者ユーザーのユーザー名、電子メールアドレス、およびパスワードを入力して、指示に従います。 終了したら、ターミナルでサーバーを再起動する必要があります。
- python manage.py runserver
Webブラウザーで、127.0.0.1:8000/admin
に移動して管理ダッシュボードにアクセスします。
このページに移動できるのは、urls.py
にadmin
が設定されているためです。
作成したユーザー名とパスワードでログインすると、Django管理ダッシュボードが表示されます。
グループとユーザーは、Djangoがアクセスできる2つのモデルを表しています。 モデルは、データベース内のテーブルの単なるコード表現です。 Djangoはさらに多くのテーブルを作成しましたが、残りのテーブルに直接アクセスする必要がないため、モデルは作成されませんでした。
[ユーザー]をクリックすると、ユーザーテーブルの詳細が表示され、作成したユーザーが表示されます。 ダッシュボードのさまざまなリンクをクリックして、何が利用できるかを確認してください。 ユーザーを削除しないように注意してください。削除しないと、createsuperuser
を再度実行する必要があります。
とりあえず管理ダッシュボードを離れて、コードに取り組みましょう。 天気予報アプリ用にプロジェクト内にアプリを作成する必要があります。
ステップ4—アプリを作成する
Djangoでは、 apps を使用して、プロジェクトの機能を分離できます。 Djangoの場合、アプリはプロジェクトの特定の機能を指します。
たとえば、settings.py
ファイルを見ると、INSTALLED_APPS
リストが表示されます。
インストールされた最初のアプリ(django.contrib.admin
)は、今使用したものです。 すべての管理機能を処理し、それ以外は処理しません。 プロジェクトのもう1つのアプリは、デフォルトでdjango.contrib.auth
です。これにより、管理ダッシュボードにログインできます。
あなたの場合、天気の表示に関連するすべてを処理する新しいアプリを作成する必要があります。
まず、サーバーを停止する必要があります。
次に、ターミナルでstartapp
コマンドを実行します。
- python manage.py startapp weather
startapp
を実行することにより、Djangoは新しいディレクトリとより多くのファイルをプロジェクトに追加しました。
最新のファイルを生成したら、weather
アプリディレクトリにurls.py
という新しいファイルを作成しましょう。
from django.urls import path
urlpatterns = [
]
このファイルは、the_weather
ディレクトリのurls.py
に似ています。 違いは、このurls.py
ファイルには、アプリ自体に関連するすべてのURLが含まれていることです。
まだURLを指定していませんが、アプリを認識し、アプリに固有のURLをアプリurls.py
ファイルにルーティングするようにプロジェクトを設定できます。
まず、settings.py
のINSTALLED_APPS
リストに移動し、weather
をリストに追加します。
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'weather',
]
...
これにより、Djangoはプロジェクトでweather
アプリを使用することを認識できます。 これを行うことで、Djangoは移行とURLを探す場所を知ることができます。
次に、元のurls.py
を変更して、アプリのurls.py
ファイルを指すようにする必要があります。 これを実現するには、管理ダッシュボードの既存のパスの下に行を追加します。 また、アプリのurls.py
ファイルをポイントできるように、include
をインポートする必要があります。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('weather.urls')),
]
空の文字列は、アプリへのエントリポイントにエンドポイントを使用する必要がないことを意味します。 代わりに、アプリに特定のエンドポイントを処理させます。 path('weather/', ...)
のようなものを配置することもできます。つまり、天気アプリに関連付けられているものを取得するには、127.0.0.1:8000/weather/
と入力する必要があります。 ただし、プロジェクトは単純なので、ここではそれを行いません。
ステップ5—テンプレートとビューを追加する
次に、テンプレートをプロジェクトに追加する必要があります。
Djangoのtemplateは、テンプレートを動的にする追加の構文を可能にするHTMLファイルです。 変数の追加、if
ステートメント、ループなどの機能を処理できるようになります。
ターミナルで、weather
アプリディレクトリに移動します。
- cd weather
次に、templates
ディレクトリを作成します。
- mkdir templates
そしてそれにナビゲートします:
- cd templates
また、アプリと同じ名前の別のディレクトリを作成します。 これは、Djangoがさまざまなアプリのすべてのテンプレートディレクトリを組み合わせているためです。 ファイル名が重複しないようにするには、アプリの名前を使用して重複を防ぐことができます。
- mkdir weather
このweather
ディレクトリ内に、index.html
という名前の新しいファイルを作成します。 これがメインテンプレートになります。
テンプレートに使用するHTMLは次のとおりです。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>What's the weather like?</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.css" />
</head>
<body>
<section class="hero is-primary">
<div class="hero-body">
<div class="container">
<h1 class="title">
What's the weather like?
</h1>
</div>
</div>
</section>
<section class="section">
<div class="container">
<div class="columns">
<div class="column is-offset-4 is-4">
<form method="POST">
<div class="field has-addons">
<div class="control is-expanded">
<input class="input" type="text" placeholder="City Name">
</div>
<div class="control">
<button class="button is-info">
Add City
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</section>
<section class="section">
<div class="container">
<div class="columns">
<div class="column is-offset-4 is-4">
<div class="box">
<article class="media">
<div class="media-left">
<figure class="image is-50x50">
<img src="http://openweathermap.org/img/w/10d.png" alt="Image">
</figure>
</div>
<div class="media-content">
<div class="content">
<p>
<span class="title">Las Vegas</span>
<br>
<span class="subtitle">29° F</span>
<br> thunderstorm with heavy rain
</p>
</div>
</div>
</article>
</div>
</div>
</div>
</div>
</section>
<footer class="footer">
</footer>
</body>
</html>
注:舞台裏では、ブルマを使用してスタイリングとレイアウトを処理しています。 ブルマとCSSフレームワークの詳細については、ブルマを知る:私の現在のお気に入りのCSSフレームワークを読むことを検討してください。
テンプレートを作成したので、ビューとURLの組み合わせを作成して、アプリで実際にこれを確認できるようにします。
DjangoのViewsは、関数またはクラスのいずれかです。 この場合、単純なビューを作成しているので、関数を作成します。 この関数をviews.py
ファイルに追加します。
from django.shortcuts import render
def index(request):
return render(request, 'weather/index.html') #returns the index.html template
ビューにindex
という名前を付けているのは、ルートURLであるアプリのインデックスにあるためです。 テンプレートをレンダリングするには、render
関数に必要なrequest
と、レンダリングするテンプレートファイルの名前(この場合はweather/index.html
)を返します。 。
このビューにリクエストを送信するURLを追加しましょう。 アプリのurls.py
ファイルで、urlpatterns
リストを更新します。
from django.urls import path
from . import views
urlpatterns = [
path('', views.index), #the path for our index view
]
これにより、作成したばかりのビューを参照できます。
Djangoは、エンドポイントのない任意のURLと一致し、作成したビュー関数にルーティングします。
次に、ターミナルを使用してプロジェクトルート(the_weather
)に戻ります。
次に、サーバーを起動します。
- python manage.py runserver
次に、Webブラウザーを開き、127.0.0.1:8000
に再度アクセスします。
index.html
ファイルのレンダリングされたHTMLを観察します。 都市を追加するための入力があります。 そして、ラスベガスのハードコードされた天気の表示があります。 ただし、この時点でのフォームは機能せず、天気は単なるプレースホルダーです。 次はそれに取り組みましょう。
ステップ6—WeatherAPIを使用する
ここで実行したいのは、 Open Weather MapAPIにサインアップすることです。 これにより、アプリに追加した都市の天気をリアルタイムで取得できます。
サイトに移動し、アカウントを作成してから、ダッシュボードのAPIキーに移動します。 提供されているデフォルトキーを使用することも、新しいAPIキーを作成することもできます。 このキーを使用すると、APIを使用して天気を取得できます。
注: APIキーを秘密にして、他のユーザーが使用できないようにすることが重要です。 APIキーをGitHubなどのリモートリポジトリにコミットしないようにする必要があります。
使用するエンドポイントの1つは以下のとおりです。そのため、APIキーを使用して次のURLを変更し、ブラウザでURLに移動すると、返されるデータを確認できます。
http://api.openweathermap.org/data/2.5/weather?q=las%20vegas&units=imperial&appid=YOUR_APP_KEY
APIキーがアクティブになるまでに数分かかる場合があるため、最初に機能しない場合は、数分後に再試行してください。
座標、温度、気象条件を含むJSON形式の応答が表示されます。
それでは、データをアプリに取り込むためのリクエストを追加しましょう。
index
ビューを更新して、お持ちのURLにリクエストを送信しましょう。
from django.shortcuts import render
import requests
def index(request):
url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY'
city = 'Las Vegas'
city_weather = requests.get(url.format(city)).json() #request the API data and convert the JSON to Python data types
return render(request, 'weather/index.html') #returns the index.html template
import requests
、url
、city
、およびcity_weather
を追加します。
これらの新しい行を使用して、リクエストの送信先となるURLを追加します。
このURLは、以前にブラウザでテストしたURLとは少し異なることに注意してください。 都市はURLの一部ではなく、変数に移動されました。 このパターンにより、将来的に他の都市名に置き換えることができます。
今のところ、都市を「ラスベガス」に設定しますが、後でデータベースから都市に設定します。
最後に、都市を使用してURLにリクエストを送信し、その都市のJSON表現を取得します。
print
をコンソールに表示すると、アドレスバーにURLを入力したときに表示されたのと同じデータが表示されます。
...
def index(request):
...
print(city_weather) #temporarily view output
return render(request, 'weather/index.html') #returns the index.html template
Webブラウザーでページをリロードすると、データがコンソールに出力されます。
これが真であることが確認されたら、コードからprint
ステートメントを削除できます。
ステップ7—テンプレートにデータを表示する
次に、データをテンプレートに渡して、ユーザーに表示できるようにする必要があります。
必要なすべてのデータを保持する辞書を作成しましょう。 返されるデータのうち、temp
、description
、およびicon
が必要になります。
...
def index(request):
...
weather = {
'city' : city,
'temperature' : city_weather['main']['temp'],
'description' : city_weather['weather'][0]['description'],
'icon' : city_weather['weather'][0]['icon']
}
return render(request, 'weather/index.html') #returns the index.html template
必要な情報がすべて揃ったので、それをテンプレートに渡すことができます。 これをテンプレートに渡すには、context
という変数を作成します。 これは、テンプレート内でその値を使用できるようにする辞書になります。
次に、render
で、3番目の引数としてcontext
を追加します。
...
def index(request):
...
context = {'weather' : weather}
return render(request, 'weather/index.html', context) #returns the index.html template
context
内に気象データを追加したら、テンプレートに移動してデータを追加しましょう。
index.html
テンプレート内で行う必要があるのは、ハードコードされた値の代わりに変数を使用するようにHTMLを変更することだけです。 変数は{{
}}
タグを使用し、コンテキストディクショナリ内のすべてを参照します。
Djangoは辞書キーを変換するため、ドット表記を使用してのみアクセスできることに注意してください。 たとえば、weather.city
は都市名を示します。 Pythonのようにweather['city']
を使用することはありません。
「ボックス」<div>
を見つけて、変数を使用するように更新します。
...
<div class="box">
<article class="media">
<div class="media-left">
<figure class="image is-50x50">
<img src="http://openweathermap.org/img/w/{{ weather.icon }}.png" alt="Image">
</figure>
</div>
<div class="media-content">
<div class="content">
<p>
<span class="title">{{ weather.city }}</span>
<br>
<span class="subtitle">{{ weather.temperature }}° F</span>
<br> {{ weather.description }}
</p>
</div>
</div>
</article>
</div>
...
すべての変数が置き換えられると、都市の現在の天気が表示されます。
ただし、都市は現在もハードコーディングされています。 次に実行したいのは、データベースからプルして、データベースにある都市を表示することです。
これを実現するには、データベースにテーブルを作成して、天気を知りたい都市を保持します。 このためのモデルを作成します。
weather
アプリのmodels.py
ファイルに移動し、次を追加します。
from django.db import models
class City(models.Model):
name = models.CharField(max_length=25)
def __str__(self): #show the actual city name on the dashboard
return self.name
class Meta: #show the plural of city as cities instead of citys
verbose_name_plural = 'cities'
これにより、都市の名前であるname
という列を持つテーブルがデータベースに作成されます。 この都市はcharfield
になります。これは単なる文字列です。
データベースでこれらの変更を取得するには、makemigrations
を実行して、データベースを更新するコードを生成し、移行してこれらの変更を適用する必要があります。
サーバーを停止してから、ターミナルで移行を実行しましょう。
- python manage.py makemigrations
そして移行します:
- python manage.py migrate
管理ダッシュボードでこのモデルを表示できるようにする必要があります。 これを行うには、admin.py
ファイルに登録する必要があります。
from django.contrib import admin
from .models import City
admin.site.register(City)
次に、サーバーを再起動し、Webブラウザーで管理ダッシュボードを表示します。
City
がオプションになりました。
次に、管理ダッシュボードに移動して、いくつかの都市を追加できます。 例:「ロンドン」、「東京」、「ラスベガス」。
データベース内のエントリを使用して、ビューでこれらのエントリをクエリする必要があります。 City
モデルをインポートしてから、そのモデルにすべてのオブジェクトを照会することから始めます。
from django.shortcuts import render
import requests
from .models import City
次に、request
をcities
で更新します。
...
def index(request):
url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY'
cities = City.objects.all() #return all the cities in the database
...
都市のリストがあるので、それらをループして各都市の天気を取得し、最終的にテンプレートに渡されるリストに追加する必要があります。
これは、前のステップで行ったことのバリエーションにすぎません。 違いは、各辞書をループしてリストに追加することです。
まず、[X21X]