首页 > 解决方案 > 当 DateTimeField 等于当前日期和时间时 Django 执行函数

问题描述

所以我在我的网站上实现了一个订阅产品。

当他们开始订阅时,当前日期和时间将存储到数据库中。当他们取消订阅时,会在开始日期上添加一段时间,以便我知道何时取消订阅并在其他地方更改一些值。

这很好,我知道如何使用 Django 和 Python,但是,当将来取消日期到来时,我被困在最后一点。

问题:当取消日期(在数据库中)等于当前日期和时间时,如何执行函数。

下面是我将使用的模型的一个简单示例:

模型.py

class Subscriptions(models.Model):
    subscription_id = models.AutoField(primary_key=True)
    start_date = model.DateTimeField(auto_now_add=True)
    cancel_date = model.DateTimeField(auto_now_add=False)
    person_id = model.ForeignKey('Persons')

class Persons(models.Model):
    person_id = models.AutoField(primary_key=True)
    value_to_change = models.BooleanField()

在你问之前我没有尝试任何代码,因为我找不到这个问题的解决方案。谢谢 <3

标签: pythondjangopython-3.x

解决方案


没有 Celery,安装在提供 CRON 的 UNIX 系统上(cron doku:例如https://www.computerhope.com/unix/ucrontab.htm):

  1. 编写一个命令https://docs.djangoproject.com/en/2.1/howto/custom-management-commands/获取取消日期为过去且尚未取消的对象。(如果您使用 datetime.now() 进行查找(具有最精细粒度的非常精确的查找),您必须非常幸运才能找到任何东西。)

您应该添加另一个日期字段来告诉您系统实际运行取消的时间,并且您应该允许 cancel_date 和 cancelled_date 都为空。

# models.py
class Subscriptions(models.Model):
    subscription_id = models.AutoField(primary_key=True)
    start_date = model.DateTimeField(auto_now_add=True)
    cancel_date = model.DateTimeField(auto_now_add=False, null=True)
    cancelled_date = model.DateTimeField(null=True)
    person_id = model.ForeignKey('Persons')

# under myapp/management/command/cancellation.py
class CancellationCommand(BaseCommand):
    def handle(self, *args, **options):
        now = datetime.now()
        to_cancel_qs = Subscriptions.objects.exclude(
            cancelled_date__isnull=False).filter(
            cancel_date__lte=now)
        for sub in to_cancel_qs.all():
            # do your cancelling
            sub.cancelled_date = now
            sub.save()
        # or: to_cancel_qs.update(cancelled_date=now)
        
  1. 安装一个通过 ./manage.py your_command 定期运行此命令的 cron 作业

推荐阅读