djangoに定期起動する機能を実装する
djangoのウェブアプリケーションで表示される情報を定期的に更新したい
現状のプロダクトでは、postgresqlにcsvのデータをコピーしただけなのでデータは変更されない。ブログのようなアプリケーションならこれで十分だけれども、定期的に情報を更新したいものには対応できない。例えば、株価、為替、天気のような情報だ。これが問題だった。情報を更新するには何が必要か調べたのでメモしておく。
情報更新に必要な要素
情報収集する際に"django クローン"で調べるといろいろ情報が出てきた。それをもとに必要な要素が確定した。
- データオブジェクトの更新
- 更新トリガーを作る
- 更新する頻度の設定
データオブジェクトの更新
データオブジェクトの更新は、views.pyの中でデータオブジェクトを抽出し、当該オブジェクトのデータを変更して、save()すれば良い。変更内容はスクレイピングなどを利用して更新したい情報を取得する。
更新トリガーを作る
更新トリガーはdjango-admin コマンドの実装を参考にした。 https://docs.djangoproject.com/ja/2.1/howto/custom-management-commands/
python manage.py hogehoge
という自作のコマンドを作成することができ、これによりコマンド入力の際にviews.pyを走らせることができるようになる。
更新する頻度の設定
これはサーバのクローンを利用する。crontabコマンドを使うと定期的に指定した日時で何らかの指示を実行してくれる。
具体的な実装手続き
実装方法には二つ方法がある。一つはdjango-extensionsを使う方法。もう一つはdjango-extensionsを使わない、いわばライブラリに頼らないで実装する方法である。
django-extensionsを使わなくても、それほど実装方法が変わることはないので後者をお勧めする。一応両方のやり方を残しておく。
django-extensionsの採用
djanogo-extensionsを利用するとcommand作成に必要なディレクトリやファイルの構造を自動で作成してくれる。だからviews.pyでどんな挙動にするかを記述することに専念することができる。またこの必要なディレクトリやファイルの構造を自分で作成するのがdjango-extensionsを使わない方法である。
django-extensionsのインストール
こちらを参考にさせていただきました。
https://tokibito.hatenablog.com/entry/20150827/1440602095
$ pip install django-extensions
settings.pyを編集する。注意点はpipインストールしたモジュール名はdjango-extensionsだけれども、追加する内容はdjango_extensionsで異なる。ハイフンとアンダーバーの違いに注意すること。間違うとコマンド作成時に以下のエラーになります。
ModuleNotFoundError: No module named 'django-extensions'
話は戻ってsettings.pyの編集。
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_extensions', # この行を追加 )
BaseCommand周りについて
実際にどのような挙動をするかを記述する場所は,management/commands/**.pyである。
ここに好きなように書くのではなく、BaseCommandクラスを継承したCommandクラスを定義する。そして自分の望む挙動を書き込む。
ドキュメント
https://docs.djangoproject.com/ja/2.2/howto/custom-management-commands/#methods
メソッドが重要であるので見てみるとよい。
BaseCommand.add_arguments(parser)メソッドは、python manage.py hogeのhogeをコマンドとして認識するようにする働きを持ちます。
BaseCommand.handle(*args, **options)メソッドは、python manage.py hogeコマンドが実行されたら、具体的に挙動するかを定める役割を持ちます。
自力で行う
django-extensionsを使わない場合はディレクトリ、ファイルを自作するだけである。
その場合はドキュメントをみてディレクトリやファイルの構造をまねて作ればよい。
- コマンドファイルを適切におくディレクトリ構造を作成
- Commandクラスを作成するコマンドファイルの作成
コマンドファイルを適切におくディレクトリ構造を作成
apps(アプリディレクトリ)以下に以下のディレクトリを設ける。
management/commands
# mkdir -p management/commands
commands以下に自分が作りたいコマンドを記したコマンドファイルを作成することになる。
Commandクラスを作成するpythonファイルの作成
apps(アプリディレクトリ)/management/commands以下にcron_command.pyを作成する。
from django.core.management.base import BaseCommand from apps.models import Mymodel #アプリディレクトリのモデルファイル import requests from bs4 import BeautifulSoup class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument('hoge') #このhogeがpython manage.py hogeのコマンド名になる def handle(self, *args, **options): url = "https://hogehogehoge" # handle以下はpython manage.py hogeコマンドが実行されたときに挙動する内容 res = requests.get(url) ... ... return render(...)
Centos7にコマンドを実行させる
crontab -e
実行したい時間を定め、ユーザーを指定、コマンドを実行する内容を記録。