Сигнал Джанго на основе значения поля даты и времени

Мне кажется, что нарезка - это не столько проблема, которая отличается от того, когда ваши собственные классы и программы плохо архивируются / разработаны.

Если я передаю объект подкласса в качестве параметра для метод, который принимает параметр суперкласса типа, я должен, конечно, знать об этом и знать внутренне, вызываемый метод будет работать только с объектом суперкласса (aka baseclass).

Мне кажется, необоснованное ожидание того, что предоставление подкласса, где запрашивается базовый класс, каким-то образом приведет к конкретным результатам подкласса, вызовет проблему разрезания. Его либо плохой дизайн при использовании метода, либо недостаточная реализация подкласса. Я предполагаю, что это обычно результат жертвовать хорошим дизайном ООП в пользу целесообразности или повышения производительности.

1
задан bloodwithmilk 26 March 2019 в 23:16
поделиться

2 ответа

В документации django есть два интересных сигнала, которые могут помочь вам в этой задаче: pre_save и post_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). [ 1112]

0
ответ дан Chiheb Nexus 26 March 2019 в 23:16
поделиться

Хорошо, благодаря комментариям @SergeyPugach, я сделал следующее:

Добавил сигнал 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)

И фактическое задание в tasks.py

import logging
from user_api.celery import app
from django.core.mail import send_mail
from django.template.loader import render_to_string


@app.task
def send_notification(self, instance):
    try:
        mail_subject = 'Your notification.'
        message = render_to_string('notify.html', {
            'title': instance.title,
            'content': instance.content
        })
        send_mail(mail_subject, message, recipient_list=[instance.user.email], from_email=None)
    except instance.DoesNotExist:
        logging.warning("Notification does not exist anymore")

Я не буду вдаваться в подробности установки сельдерея, там много информации.

Теперь я попытаюсь выяснить, как обновить задачу после обновления экземпляра уведомления, но это совсем другая история.

0
ответ дан bloodwithmilk 26 March 2019 в 23:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: