创建后经过1个月后需要更新字段的Celery任务

问题描述

想法是创建芹菜任务,其中创建后1个月( created_at 字段) 使用5%的折扣更新价格字段。

型号:

class Product(models.Model):
    price = models.DecimalField(max_digits=15,decimal_places=2,help_text="Current price of products")
    old_price = models.DecimalField(max_digits=15,help_text="Old price of products",null=True,blank=True)
    created_at = models.DateTimeField(auto_Now_add=True,editable=False)

解决方法

您可以编写一些逻辑来检查当前日期是否已过created_at,而不是执行芹菜任务,并在这种情况下应用折扣。例如,使用https://jwt.io/

from dateutil.relativedelta import relativedelta
from django.utils.timezone import now
from decimal import Decimal

class Product(models.Model):
    price = models.DecimalField(
        max_digits=15,decimal_places=2,help_text='Current price of products'
    )
    created_at = models.DateTimeField(auto_now_add=True,editable=False)

    @property
    def real_price(self):
        if created_at + relativedelta(month=1) < now():
            return self.price * Decimal('0.95')
        return self.price

或者我们可以使用注释:

from django.utils.timezone import now
from django.db.models import Case,DecimalField,F,Value,When
from dateutil.relativedelta import relativedelta
from decimal import Decimal

Product.objects.annotate(
    real_price=Case(
        When(
            created_at__lt=now() - relativedelta(month=1),then=F('price') * Decimal('0.95')
        ),default=F('price'),output_field=DecimalField(max_digits=15,decimal_places=2)
    )
)

这里,来自查询集的Product具有额外的属性.real_price,因此一个月后可以打折。

,

@Willem建议使用一种很好的方法,但是如果您仍然想更新字段本身,则可以使用每天运行的芹菜任务。这样,您不必为每个产品实例运行celery任务,而是每天运行一次并检查所有产品并将折扣应用到30天前创建的产品的定期celery任务:

from datetime import timedelta
from django.utils import timezone


@task
def apply_discount():
    Product.objects.filter(
        created__lte=timezone.now() - timedelta(days=30),created__gt=timezone.now() - timedelta(days=31)
    ).update(price=F('price') * Decimal('0.95'))

然后将任务注册到您的设置文件中:

CELERY_BEAT_SCHEDULE = {
    'apply-discount': {
        'task': 'app.tasks.apply_discount','schedule': crontab(hour=1,minute=0),}
}

这会在每天凌晨1点运行任务

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...