【问题标题】:Celery Tasks on Django ModelsDjango 模型上的 Celery 任务
【发布时间】:2018-08-13 11:16:36
【问题描述】:

我正在尝试学习如何使用 celery 在我的一个模型上每天检查日期。我的一个模型包含一个到期日期和一个布尔字段,表示他们的保险是否过期。

模型很大,所以我要发布一个精简版。我想我有两个选择。要么在模型方法上运行 celery 任务,要么在我的 tasks.py 中重写函数。然后我需要使用 Celery beat 来运行计划以每天检查。

我的函数可以工作,但我直接传入模型对象,我认为这是错误的。

我在如何使用 celery.py 中的 celery beat 调度程序中的 args 时也遇到了麻烦。

我真的很接近让它工作,但我认为我正在以错误的方式执行任务。而且我认为在模型方法上执行任务可能是最干净的,我只是不确定如何完成。

models.py

class CarrierCompany(models.Model):
    name = models.CharField(max_length=255, unique=True)
    insurance_expiration = models.DateTimeField(null=True)
    insurance_active = models.BooleanField()

    def insurance_expiration_check(self):
        if self.insurance_expiration > datetime.today().date():
            self.insurance_active = True
            self.save()
            print("Insurance Active")
        else:
            self.insurance_active = False
            self.save()
            print("Insurance Inactive")

tasks.py

from __future__ import absolute_import, unicode_literals
from celery.decorators import task
from datetime import datetime, date
from django.utils import timezone
from .models import CarrierCompany



@task(name="insurance_expired")
def insurance_date():
    carriers = CarrierCompany.objects.all()
    for carrier in carriers:
        date = datetime.now(timezone.utc)
        if carrier.insurance_expiration > date:
            carrier.insurance_active = True
            carrier.save()
            print("Insurance Active")
        else:
            carrier.insurance_active = False
            carrier.save()
            print("Insurance Inactive")

芹菜.py

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from celery.schedules import crontab

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local')

app = Celery('POTRTMS')

app.config_from_object('django.conf:settings', namespace='CELERY')

app.autodiscover_tasks()


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))


app.conf.beat_schedule = {
    'check-insurance-daily': {
        'task': 'insurance_expired',
        'schedule': crontab(hour='8')
    },
}

*** 更新了节拍时间表以反映我真正想要运行它的时间。

【问题讨论】:

  • 哇,我使用了错误的设置文件,所以我的任务无法访问数据库。我已经解决了这个问题,我正在这里更新我的代码。我仍然认为我称我的模型对象是错误的。
  • 嘿,我明白了,你想将运营商传递给函数吗? Bc 你让它得到里面的对象,这很好,所以不需要向函数传递任何值。另外,我会使用 celery-beat bc,它很容易设置并且可以正常工作。在模型中,如果您将该函数定义为属性,则在循环运营商时,您可以调用运营商.insurance_expiration_check。如果我在正轨上,我可以给出更深入的答案,或者如果你想走另一条路,我也可以尝试并提供帮助......
  • @CoolestNerdIII 哎呀,是的,你肯定走在正确的轨道上。我已经删除了将“运营商”传递到函数中,现在可以按预期工作。 1. 现在我的问题是,在使用 celery 时将这样的模型对象传递给函数是否可以,听起来可以。 2. 第二部分听起来是编写代码的更好方法。在模型中调用它。这就是我真正迷失芹菜和芹菜节拍的地方。
  • 我想我以为我已经在使用 celery-beat,方法是在我的 celery.py 中使用 app.conf.beat_schedule
  • 我可能只需要举一个例子来回答,但是这样称呼它很好。如果您调用该函数并传递一个对象而不是一个 ID,就会出现问题(您现在什么都不传递,所以您很好)。我将在答案中举一个例子,因为这里没有足够的空间。

标签: django celery celery-task celerybeat


【解决方案1】:

我如何做的一个例子如下。此外,如果您在 Django 应用程序中包含时区,而不是使用传统的日期时间,您可能希望使用此处找到的时区库。

models.py

class CarrierCompany(models.Model):
    ...

    @property
    def is_insurance_expired(self):
        from django.utils import timezone
        if self.insurance_expiration > timezone.datetime.today():
            print("Insurance Active")
            return True
        else:
            print("Insurance Active")
            return False

tasks.py

def insurance_date():
    carriers = CarrierCompany.objects.all()
    for carrier in carriers:
        if carrier.is_insurance_expired:
            carrier.insurance_active = True
            carrier.save()
        else:
            carrier.insurance_active = False
            carrier.save()

您还可以做其他事情,例如如果它为 False 则不更新它并设置为默认 False,或者在 True 情况下反之亦然。你也可以在模型函数中完成所有这些,尽管我个人喜欢将逻辑分开一点(就像我组织我的东西的方式一样)。希望这可以帮助您摆脱困境。

【讨论】:

  • 好的,我们开始吧,我更喜欢这个。现在任务正在基于模型中的函数运行。这更多的是我想要完成的。在时区。使用我所拥有的是避免此错误的唯一方法:TypeError: can't compare offset-naive and offset-aware datetimes
  • @KrisTryber 你得到一个TypeError: can't compare offset-naive and offset-aware datetimes,因为你试图比较一个带时区信息的日期时间对象和一个不带时区信息的日期时间对象。您可能希望通过使用 django.utils.timezone.make_aware() docs.djangoproject.com/en/2.0/ref/utils/… 让您的天真日期时间对象时区感知
猜你喜欢
  • 2019-02-16
  • 2013-03-25
  • 2019-12-15
  • 2016-08-13
  • 2016-05-23
  • 2013-10-16
  • 1970-01-01
  • 2012-08-26
  • 2012-05-05
相关资源
最近更新 更多