Django - 预定事件

Django - Scheduled event

我想在当前日期超过 expiration_date 时更改此模型的 status。我正在阅读有关 Celery 的后台任务和异步任务的信息……我走的路对吗?有更直接的方法吗?如果有人可以给我提示或可以遵循的东西,我将不胜感激。感谢收听。

class MyModel(models.Model):
    status          = models.BooleanField...
    expiration_date = models.DateField....
    [...]

你不需要在模型中存储 status,你可以简单地 .annotate(..) [Django-doc] 它,所以如果模型看起来像:

class MyModel(models.Model):
    expiration_date = models.DateField(db_index=True)

所以 没有 status 字段。然后你可以做一个注释:

from django.db.models import BooleanField, ExpressionWrapper, Q
from django.db.models.functions import Now

MyModel.objects.<b>annotate(</b>
    satus=ExpressionWrapper(
        <b>Q(expiration_date__gt=Now())</b>,
        output_field=BooleanField()
    )
)

如果expiration_date在未来,从这个查询集产生的MyModel对象将有一个额外的属性.status,即True

如果您经常需要这个,您可以制作一个 manager [Django-doc],它会在您每次访问 MyModel.objects:

时自动为项目添加注释
from django.db.models import BooleanField, ExpressionWrapper, Q
from django.db.models.functions import Now

class <b>MyModelManager</b>(models.Manager):

    def get_queryset(self, *args, **kwargs):
        super().get_queryset(*args, **kwargs).<b>annotate(</b>
            satus=ExpressionWrapper(
                <b>Q(expiration_date__gt=Now())</b>,
                output_field=BooleanField()
            )
        )

class MyModel(models.Model):
    expiration_date = models.DateField(db_index=True)

    <b>objects = MyModelManager()</b>

这不需要难以管理的计划任务:如果您稍后编辑 expiration_date,那么您需要以某种方式 "remove" 已经计划的任务并计划一个新任务,可以是 "tricky"。如果计划的任务已经完成,那么您必须 "undo" 它。

通过使用注释,您可以确保 status 仅基于 expiration_dateNow() 相比的值。