naritoブログ

【お知らせ】
新ブログができました。今後そちらで更新し、このサイトは更新されません(ウェブサイト自体は残しておきます)
このブログの内容に関してコメントしたい場合は、新ブログのフリースペースに書き込んでください

このブログの内容を新ブログに移行中です。このブログで見つからない記事は、新ブログにありま

Djangoでcron

約1580日前 2016年5月25日0:13
プログラミング関連
Django Python
Webアプリケーションで、定期的に実行したい処理がある、という状況があります
例えば外部のサイトを1時間おきにスクレイピングしその結果を登録、そして表示する、なんて場合です

今回は
・Djangoのコマンドを作成する
・そのコマンドをcronで定期的に実行する
という流れです

プロジェクト名はtest
アプリケーションはcronとします

また、cronの実行環境はCentos6
プロジェクトへのパスは/usr/webapps/test
となります

test/test/urls.py

from django.conf.urls import include, url,patterns
urlpatterns = [
url(r'^cron/', include('cron.urls', namespace='cron')), # 追加する
]


test/test/settings.py

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"cron", # 追加する
)




わかりやすくするため、views.pyやテンプレートも作成してみます
test/templates/cron/base.html

<!DOCTYPE html>
<html>
<head lang="ja">
<meta charset="UTF-8">
<title>くろん</title>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>


test/templates/cron/index.html

{% extends "cron/base.html" %}
{% block body %}
<table border="1">
<thead>
<tr>
<th>message</th>
<th>created_at</th>
<th>updated_at</th>
</tr>
</thead>
<tbody>
{% for message in messages %}
<tr>
<td>{{ message.message }}</td>
<td>{{ message.created_at }}</td>
<td>{{ message.updated_at }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}


test/cron/views.py

from django.shortcuts import render
from .models import Message


def index(request):
d = {
'messages': Message.objects.all(),
}
return render(request, 'cron/index.html', d)


test/cron/models.py

from django.db import models

class Message(models.Model):
message = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return self.message




画面は、このような感じです。わかりやすく一件たしてます


コマンドを作成していきます。test/cronにmanagementというディレクトリを作成し、その中に、commandsというディレクトリを作成。


最後に、 python manage.py コマンド名
のコメンド名にあたる名前で作成します。今回は、python manage.py makeとしたかったのでmake.pyにしました


make.pyの中身はこうです

from django.core.management.base import BaseCommand
from cron.models import Message

class Command(BaseCommand):

def add_arguments(self, parser):
parser.add_argument('message')


def handle(self, *args, **options):
message = options['message']
Message(message=message).save()
print("{0}の追加が完了しました".format(message))



これは引数が入力できるようにしています。つまり、python manage.py make メッセージ
とできるようになります

def add_arguments(self, parser):
parser.add_argument('message')



コマンドが実行されたときのメインになる部分です
今回はメッセージを取得し、それを元にMessageモデルを作成しsaveしています

def handle(self, *args, **options):
message = options['message']
Message(message=message).save()
print("{0}の追加が完了しました".format(message))



使い方はこのようになります



では、これを定期的に実行するようにしましょう
今回の環境はCentOS6です
cronは既に動いているものとします


下記コマンドでcronの編集ができます

crontab -e


下記をを追記

0 * * * * /usr/local/bin/python3.5 /usr/webapps/test/manage.py make 0時です >>/tmp/cron.log 2>>/tmp/cron_error.log



書式は

分 時 日 月 曜日 実行ユーザ 実行コマンド


となっています


これは、毎時0分に実行するという意味です

0 * * * *


0分と30分に実行したいなら、こうです

0,30 * * * *


これはpythonのパスです。virtualenvの場合は、そのパスにしましょう

/usr/local/bin/python3.5


Djangoプロジェクトのパスになります。フルパスにするのを忘れないようにしましょう

/usr/webapps/test/manage.py make 0時です


これはログの設定です。
通常のログを/tmp/cron.logに、エラーのログを/tmp/cron_error.logにしています
ログをメールで送信したり、ログローテーションだとかあるので、詳しい人はやってみるとよいでしょう
 
>>/tmp/cron.log 2>>/tmp/cron_error.log


参考
http://stackoverflow.com/questions/30230490/django-custom-command-error-unrecognized-arguments
たこみ 約397日前 2019年8月21日10:29
**optionsではなく、*argsに値を入れたい場合はどのように入れられますか?
下記のようにしたのですが、上手くいかなくて。教えてください。
何か定義しなくてはいけないのでしょうか?

call_command('hoge', self.contract.id)

エラー内容:
{CommandError}Error: unrecognized arguments: 1