在Django中使用crontab

13 投票
7 回答
38639 浏览
提问于 2025-04-16 00:58

我需要创建一个每天通过定时任务发送新闻邮件的功能。我在网上找到了两种方法:

第一种 - 把文件放在django项目文件夹里:

#! /usr/bin/env python
import sys
import os

from django.core.management import setup_environ
import settings
setup_environ(settings)

from django.core.mail import send_mail
from project.newsletter.models import Newsletter, Address

def main(argv=None):
    if argv is None:
        argv = sys.argv

    newsletters = Newsletter.objects.filter(sent=False)
    message = 'Your newsletter.'

    adr = Address.objects.all()
    for a in adr:
        for n in newsletters:
            send_mail('System report',message, a ,['user@example.com'])

if __name__ == '__main__':
    main()

我不太确定这样做是否可行,也不太清楚怎么运行。假设这个文件叫run.py,那我是不是可以在定时任务中用 0 0 * * * python /path/to/project/run.py 来调用它呢?

第二种解决方案 - 在任何地方创建我的发送函数(就像普通的django函数一样),然后再创建一个run.py脚本:

import sys
import os

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

module_name = sys.argv[1]
function_name = ' '.join(sys.argv[2:])

exec('import %s' % module_name)
exec('%s.%s' % (module_name, function_name))

然后在定时任务中调用:0 0 * * * python /path/to/project/run.py newsletter.views daily_job()

哪种方法可行,或者哪种更好呢?

7 个回答

3

我建议你看看 django-chronograph。简单来说,它能做到你想要的功能,跟其他建议类似,而且它还提供了一个通过管理面板来管理你的定时任务的选项。定时任务需要作为 Django 命令来实现。然后你可以通过调用

python manage.py cron

来运行所有待处理的任务,这个调用应该由你的定时任务触发。

11

Ashok提到通过cron来运行管理命令的方法效果不错,但如果你想要一个更强大的解决方案,可以考虑使用一个叫做Kronos的库:

# app/cron.py

import kronos

@kronos.register('0 * * * *')
def task():
    pass
38

我建议你把你的功能做成一个 Django 管理命令,然后通过 crontab 来运行它。

如果你的命令是 send_newsletter,那么只需要这样做:

0 0 * * * python /path/to/project/manage.py send_newsletter

在这种情况下,你不需要担心设置配置模块。

撰写回答