https://medium.com/@mrgrantanderson/replacing-cron-and-running-background-tasks-in-django-using-apscheduler-and-django-apscheduler-d562646c062e 解释了如何设置包含调度程序的 AppConfig:
为此,您必须将以下内容添加到您的settings.py:
INSTALLED_APPS = [
...
"django_apscheduler",
]
# This scheduler config will:
# - Store jobs in the project database
# - Execute jobs in threads inside the application process
SCHEDULER_CONFIG = {
"apscheduler.jobstores.default": {
"class": "django_apscheduler.jobstores:DjangoJobStore"
},
'apscheduler.executors.processpool': {
"type": "threadpool"
},
}
SCHEDULER_AUTOSTART = True
启动调度程序的文件可能如下所示:
import logging
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.executors.pool import ProcessPoolExecutor, ThreadPoolExecutor
from django_apscheduler.jobstores import register_events, register_job
from django.conf import settings
# Create scheduler to run in a thread inside the application process
scheduler = BackgroundScheduler(settings.SCHEDULER_CONFIG)
def start():
if settings.DEBUG:
# Hook into the apscheduler logger
logging.basicConfig()
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
# Adding this job here instead of to crons.
# This will do the following:
# - Add a scheduled job to the job store on application initialization
# - The job will execute a model class method at midnight each day
# - replace_existing in combination with the unique ID prevents duplicate copies of the job
scheduler.add_job("core.models.MyModel.my_class_method", "cron", id="my_class_method", hour=0, replace_existing=True)
# Add the scheduled jobs to the Django admin interface
register_events(scheduler)
scheduler.start()
以及将像这样启动调度程序的 AppConfig:
from django.conf import settings
class CoreConfig(AppConfig):
name = "core"
def ready(self):
from . import scheduler
if settings.SCHEDULER_AUTOSTART:
scheduler.start()
(从上面链接的教程中复制的所有代码)。
但是请注意,django-apscheduler 在其 README 中声明
这种简单性的权衡是您需要小心确保只有一个调度程序在特定时间点有效运行。 (https://github.com/jcass77/django-apscheduler#quick-start)。
如果您在多线程 Django 环境中高效地运行调度程序,据我所知,这并不能保证。因此,这个解决方案绝对应该持保留态度 - 更正确的方法是遵循 README 的建议并为调度程序创建一个阻塞命令,并独立于您在专用进程中提供的服务运行该命令。