首页 > 解决方案 > 经过一段时间后如何在Django中运行函数

问题描述

Station具有以下字段的模型:

class Station(models.Model):
    is_available = models.BooleanField(default=True)
    unavailable_until = models.DateTimeField(null=True,blank=True)

我可以通过给出一个值来定义我的站点何时不可用DateTime,因此当该操作发生时,is_available值将变为False

我想将is_available值转换为True每次unavailable_until传递的值(与基于时区的当前时间比较)。

我怎样才能实现这样的自动化?

想象一下,我有很多Station属于电台所有者的记录,它们可以随时更新可用性(unavailable_until如果通过,则分配新值)。

我认为逻辑可能是这样的:

def turn_availability_to_true(station):
   if (station.unavailable_until < current_time):
       station.is_available = True

但是我怎样才能实现这样的函数,当unavailable_until值传递时由它自己调用呢?

标签: djangoasynchronous

解决方案


.annotate(…)如果可用,您可以[Django-doc]动态计算,而不是使用字段Station

因此模型看起来像

class Station(models.Model):
    # no is_available
    unavailable_until = models.DateTimeField(null=True,blank=True)

我们对此进行注释:

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

Station.objects.annotate(
    is_available=ExpressionWrapper(
        ~Q(unavailable_until__gte=Now()),
        output_field=BooleanField()
    )
)

如果你经常需要这个,你可以实现一个管理器[Django-doc],它会自动将它添加到Stations:

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

class StationManager(models.Manager):
    
    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).annotate(
            is_available=ExpressionWrapper(
                ~Q(unavailable_until__gte=Now()),
                output_field=BooleanField()
            )
        )

class Station(models.Model):
    # no is_available
    unavailable_until = models.DateTimeField(null=True,blank=True)
    objects = StationManager()

unavailable_until不运行计划任务的优点是,如果稍后修改字段,例如修改到以后的日期,则很难更改该任务。在这种情况下,必须删除已安排的任务,并安排新的任务。通过注释,我们避免了同步问题。


推荐阅读