基于datetime字段值的Django信号

时间:2019-03-24 13:08:26

标签: django celery django-signals

我正在努力解决以下问题。 我正在尝试创建一个自定义信号,该信号将在当前时间等于模型的notify_on DateTimeField的值时触发。

类似这样的东西:

class Notification(models.Model):
    ...
    notify_on = models.DateTimeField()



def send_email(*args, **kwargs):
    # send email


signals.when_its_time.connect(send_email, sender=User)

阅读完所有文档后,我没有发现有关如何实现此类信号的信息。

有什么想法吗?

更新: 较幼稚的方法,可以丢弃无关的任务:https://stackoverflow.com/a/55337663/9631956

2 个答案:

答案 0 :(得分:2)

在django的文档中,有两个有趣的信号可以帮助您完成此任务:pre_savepost_save。 这取决于您的需求,但是,假设您要在保存模型后检查模型的notify_on是否等于当前日期(实际上是在调用save()create()方法之后)。如果是您的情况,可以执行以下操作:

from datetime import datetime
from django.contrib.auth.models import User
from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save


class Notification(models.Model):
    ...
    # Every notification is related to a user
    # It depends on your model, but i guess you're doing something similar
    user = models.ForeignKey(User, related_name='notify', on_delete=models.DO_NOTHING)
    notify_on = models.DateTimeField()
    ...
    def send_email(self, *args, **kwargs):
        """A model method to send email notification"""
        ...


@receiver(post_save, sender=User)
def create_notification(sender, instance, created, **kwargs):
    # check if the user instance is created
    if created:
        obj = Notification.objects.create(user=instance, date=datetime.now().date())
        if obj.notify_on == datetime.now().date():
            obj.send_email()

您应该知道,只有有触发它们的动作,django信号才能由它们自己拥有。这意味着Django信号不会在模型的实例上循环并执行操作,但是django信号将在您的应用程序对连接到信号的模型执行操作时触发。

奖励::要对实例执行循环并定期处理操作,您可能需要具有async数据库(主要是Queue)的Celery工作人员Redis or RabbitMQ)。

答案 1 :(得分:1)

好,感谢@SergeyPugach的评论,我做了以下工作:

添加了一个var photo = true; // Will capture picture. if (photo) { // 'true' is a truthy value. capturePhoto(); } else { // Do nothing } 信号,该信号调用了一个将任务添加到芹菜的函数。 @ClientEndpoint class MyClientEndpoint { @OnOpen def onOpen(session: Session): Unit = { log.debug("New session opened: " + session.getId) } @OnClose def onClose(session: Session, reason: CloseReason): Unit = { log.debug(s"Session[${session.getId}] closed: " + reason) } @OnMessage def onMessage(message: String): Unit = { log.debug("Received: " + message) } } 让您通过post_save-可以直接接受apply_async的预计到达时间,这非常方便。

eta

还有DateTimeField

中的实际任务
# models.py
from django.db.models import signals
from django.db import models
from .tasks import send_notification

class Notification(models.Model):
    ...
    notify_on = models.DateTimeField()


def notification_post_save(instance, *args, **kwargs):
    send_notification.apply_async((instance,), eta=instance.notify_on)


signals.post_save.connect(notification_post_save, sender=Notification)

我不会介绍设置芹菜的细节,那里有很多信息。

现在,我将尝试找出在通知实例更新后如何更新任务,但这是一个完全不同的故事。