我一直在使用Django开发一个web应用程序,我很好奇是否有一种方法可以安排一个作业定期运行。

基本上,我只是想运行数据库,并在自动的、定期的基础上进行一些计算/更新,但我似乎找不到任何关于这样做的文档。

有人知道怎么设置吗?

澄清一下:我知道我可以设置一个cron作业来完成这个任务,但我很好奇Django中是否有一些特性提供了这个功能。我希望人们能够自己部署这个应用程序,而不需要做很多配置(最好是零配置)。

我曾经考虑过“回溯性”地触发这些操作,方法是简单地检查自上一次请求发送到站点以来作业是否应该运行,但我希望使用更简洁的方法。


当前回答

是的,上面的方法太棒了。我尝试了其中一些。最后,我找到了这样一个方法:

    from threading import Timer

    def sync():

        do something...

        sync_timer = Timer(self.interval, sync, ())
        sync_timer.start()

就像递归一样。

好的,我希望这个方法能满足你的要求。:)

其他回答

如果您使用的是标准POSIX操作系统,则使用cron。

如果使用Windows,则使用at。

编写一个Django管理命令

弄清楚他们在哪个站台。 为您的用户执行适当的“AT”命令,或者为您的用户更新crontab。

我只是想到了一个相当简单的解决方案:

定义一个视图函数do_work(req, param),就像使用其他任何视图一样,使用URL映射,返回一个HttpResponse等等。 使用您的定时首选项(或在Windows中使用AT或Scheduled Tasks)设置一个运行curl http://localhost/your/mapped/url?param=value的cron作业。

你可以添加参数,但只是将参数添加到URL。

告诉我你们的想法。

[更新]我现在使用runjob命令从django扩展而不是curl。

我的cron看起来是这样的:

@hourly python /path/to/project/manage.py runjobs hourly

... 每天,每月等等。还可以将其设置为运行特定作业。

我觉得这样更容易管理,也更干净。不需要将URL映射到视图。只需定义作业类和crontab,就完成了。

简单的方法是编写一个自定义shell命令,参见Django文档,并在linux上使用cronjob执行它。然而,我强烈建议使用像RabbitMQ这样的消息代理加上芹菜。也许你可以看看 本教程

对于简单的dockerized项目,我真的看不到任何现有的答案适合。

所以我写了一个非常简单的解决方案,不需要外部库或触发器,它可以自己运行。不需要外部os-cron,应该可以在任何环境下工作。

它通过添加一个中间件来工作:middleware.py

import threading

def should_run(name, seconds_interval):
    from application.models import CronJob
    from django.utils.timezone import now

    try:
        c = CronJob.objects.get(name=name)
    except CronJob.DoesNotExist:
        CronJob(name=name, last_ran=now()).save()
        return True

    if (now() - c.last_ran).total_seconds() >= seconds_interval:
        c.last_ran = now()
        c.save()
        return True

    return False


class CronTask:
    def __init__(self, name, seconds_interval, function):
        self.name = name
        self.seconds_interval = seconds_interval
        self.function = function


def cron_worker(*_):
    if not should_run("main", 60):
        return

    # customize this part:
    from application.models import Event
    tasks = [
        CronTask("events", 60 * 30, Event.clean_stale_objects),
        # ...
    ]

    for task in tasks:
        if should_run(task.name, task.seconds_interval):
            task.function()


def cron_middleware(get_response):

    def middleware(request):
        response = get_response(request)
        threading.Thread(target=cron_worker).start()
        return response

    return middleware

模型/ cron.py:

from django.db import models


class CronJob(models.Model):
    name = models.CharField(max_length=10, primary_key=True)
    last_ran = models.DateTimeField()

settings.py:

MIDDLEWARE = [
    ...
    'application.middleware.cron_middleware',
    ...
]

我采用的一个解决方案是这样的:

1)创建一个自定义管理命令,例如:

python manage.py my_cool_command

2)使用cron(在Linux上)或at(在Windows上)在需要的时间运行我的命令。

这是一个简单的解决方案,不需要安装沉重的AMQP堆栈。然而,使用像芹菜这样的东西有很好的优点,在其他答案中提到过。特别是,使用芹菜,不需要将应用程序逻辑扩展到crontab文件中是很好的。然而,cron解决方案非常适合中小型应用程序,并且不需要大量外部依赖。

编辑:

在windows的后续版本中,at命令在windows 8、Server 2012及以上版本中已弃用。你可以使用schtasks.exe来做同样的事情。

****更新**** 这是django doc中用来编写自定义管理命令的新链接