Python 如何使用django后台任务
我正在申请django。为了根据行和注释计算提要的排名,我尝试使用django后台任务。我在节点模型中使用的功能是:Python 如何使用django后台任务,python,django,background-task,Python,Django,Background Task,我正在申请django。为了根据行和注释计算提要的排名,我尝试使用django后台任务。我在节点模型中使用的功能是: @background(schedule=60) def get_score(self): p = self.likes+self.comments # popularity t = (now()-self.date).total_seconds()/3600 # age_in_hrs # last_acti
@background(schedule=60)
def get_score(self):
p = self.likes+self.comments # popularity
t = (now()-self.date).total_seconds()/3600 # age_in_hrs
# last_activity =
n = self.admin_score
score = (p/pow((t+1), 1.2))*n
self.score = score
return score
但我看不到分数有任何变化。这意味着我正在以一种正确的方式做这件事,我缺少了基本的概念。有人能告诉我如何使用django后台任务来安排任务或让我参考一些现有的文档吗。您应该按照描述运行
python manage.py process\u tasks
。您可以将其添加到crontab以定期执行
UPD:
process\u tasks
,因为此命令每5秒在内部休眠一次(此值可配置),然后再次检查是否有任何任务要运行id
,通过id
获取对象并进行计算并保存您的对象你似乎用错了方法 假设您必须执行某些特定任务,例如,在用户注册后5分钟发送邮件。所以你要做的是: 使用django后台任务创建任务
@background(schedule=60*5)
def send_html_mail_post(id, template):
u = User.objects.get(id=id)
user_email = u.email
subject = "anything"
html_content = template.format(arguments)
from_email, to = from_email, user_email
text_content = ''
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send()
顶部的decorator定义调用函数后实际事件发生的时间
需要的时候打电话
def create_user_profile(sender, instance, created, **kwargs):
if created:
up = UserProfile.objects.create(user=instance)
up.save()
tasks.send_welcome_email(up.user.id, template=template)
这将创建任务并将其保存在数据库中,还将执行任务的时间存储在db中
您想要做的事情,定期做一些事情,可以通过创建cron作业更容易地完成
您要做的是,创建一个函数,如问题中所示。然后定义一个cron作业,每5分钟或任意间隔调用一次。django后台任务和django后台任务之间有区别。
django后台任务未维护,与较新的django版本不兼容。不久前,我们使用新功能对其进行了更新和扩展,并在上维护了新的向后兼容包django background tasks。新的django background tasks应用程序可以从下载或安装。因为这个问题似乎很一般,我相信根据我的个人经验,这是关于“如何使用django background tasks”的快速备忘单的正确位置。希望我不是唯一一个使用它的人:) 环境
- Python 3.8
- Django 3.1
> pipenv shell
(my-django-project) bash-3.2$ python manage.py migrate
创建和注册任务
任何Python函数都可以是一项任务,我们只需应用@background注释即可注册它:
from background_task import background
@background(schedule=10)
def do_something(s1: str, s1: str) -> None:
"""
Does something that takes a long time
:param p1: first parameter
:param p2: second parameter
:return: None
"""
pass
现在我们可以在项目中像往常一样调用函数:
do_something("first parameter", "second parameter")
需要注意的是,调用函数并不实际执行其代码;相反,任务记录由“django background tasks”模块存储到数据库中,更准确地说是存储到“background_Task”表中。因此,编写一个返回某些内容的任务函数没有什么用处,因为该任务稍后将在后台执行,因此调用该函数时返回的“值”几乎没有意义。我看到的返回值的唯一用例是出于测试目的,请参阅下面的测试任务部分
处理任务
为了实际运行已注册的任务,我们必须使用以下管理命令:
> python manage.py process_tasks
有关命令选项的说明,请参阅。
正如其他用户已经指出的,通常将此命令包装在cron作业中,以确保定期处理任务。在这种情况下,duration选项可能很有用:它表示process_task命令保持运行的秒数。默认情况下,持续时间为0,这意味着“永远运行”,但在我看来,这是相当危险的,因为如果由于某种原因命令崩溃或中断,您的任务将不再被处理,并且可能需要很长时间才能实现
更好的方法是将持续时间设置为定义良好的时间,例如15分钟,然后将cron作业配置为每15分钟运行一次,以重新启动处理命令。这样,如果命令崩溃,它将在稍后由cron作业重新启动
测试任务
通过“process_tasks”管理命令测试任务很糟糕,我们应该坚持使用Python模块,这也是“Django方式”
当然,我不会在这篇文章中讨论unittest,我只想指出,在单元测试期间,您希望以同步方式执行函数,就像普通Python函数一样。其语法如下所示:
do_something.now("first parameter", "second parameter")
修饰符“now”运行函数并等待其终止。在我看来,这是返回值有用的唯一用例。有了返回值,您就可以使用unittest提供的“assert*”函数的全部功能
检查任务是否已在运行
有时,您可能不希望同一任务运行多次。例如,我经常使用背景任务来训练机器学习模型,这需要很多时间。为了防止我的数据被弄乱,我更喜欢确保在上一个训练任务完成之前,不能在同一个模型上启动另一个训练任务
为了让它工作,我必须在开始新任务之前检查任务是否已经在运行;但是如何唯一地识别任务呢?对我来说,简单的方法是为任务分配一个“详细名称”,这可以在计划任务时完成:
do_something("first parameter", "second parameter", verbose_name="my_task_verbose_name")
现在,如果我想检查这个任务是否已经在运行,我可以简单地读取background_task表并验证没有任务
do_something.now("first parameter", "second parameter")
do_something("first parameter", "second parameter", verbose_name="my_task_verbose_name")
from background_task.models import Task
tasks = Task.objects.filter(verbose_name="my_task_verbose_name")
if len(tasks) == 0:
# no task running with this name, go ahead!
pass
else:
# task already running
pass