如何让Django每个mod只运行一次命令

2024-04-26 13:09:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我们将django MPTT用于树项目,我必须为树项目被修改时的自动电子邮件通知创建功能。绝对直接使用保存信号,但是-如果修改了父项,则发送n(n是子项数+父项数)电子邮件,而不是只发送一封(因为父项的更改是自动对子项进行的)。有没有一个很好的方法来防止这种情况,并基本上告诉Django“请只发送一个模型的电子邮件”?你知道吗

我想到的最好的方法是一种黑客方法(也是一种相当糟糕的黑客方法):在数据库中添加一个模型,当父项被修改时,该模型会被更新,而且孩子们在发送电子邮件之前总是检查该模型。一、 e.如果HiddenModel存在,不要发送电子邮件,否则发送电子邮件。大约五秒钟后(可能在另一个线程中)删除/撤消对HiddenModel对象的修改。它可能会工作,但从性能角度看,它只是坏的,所有这些数据库查询。你知道吗

编辑:型号:(简称SO,此表可能有错误)

从mptt.型号导入MPTTModel,树键

class TreeItem(MPTTModel):
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children')

    users = models.ManyToManyField('accounts.User', blank=True)

    name = models.CharField(max_length=255)

    @property
    def tree_path(self):
        if self.is_root_node():
            return []

        tree = self.get_ancestors(include_self=False, ascending=False)
        return list(map(lambda item: item.name, tree))

    def save(self, *args, **kwargs):
        is_new = self.pk is None
        if not is_new:
            prev_allowed_users = TreeItem.objects.get(pk=self.pk).users.all()

        super().save(*args, **kwargs)

        new_allowed_users = self.users.all()
        if is_new:
            self.send_access_email(list(new_allowed_users)) #TODO
        else:
            if prev_allowed_users != new_allowed_users:
                send_to = self.get_new_access_users(prev_allowed_users, new_allowed_users) # TODO
                self.send_access_email(send_to)

    def get_new_access_users(self, prev_users, new_users):
        send_to = []
        for user in new_users:
            if user not in prev_users:
                send_to.append(user)

        return send_to

    def send_access_email(self, recipient_list):

        email_content = 'example'

        email = EmailMessage(
            'subject',
            email_content,
            'ex@ample.com',
            recipient_list)

        print("Sending email to %s users" % str(len(recipient_list)))

Tags: to方法模型selfsendnewifaccess
1条回答
网友
1楼 · 发布于 2024-04-26 13:09:32

您需要某种注册表来确定对象是保存在外部还是作为树遍历级联的一部分。使用类变量似乎是一种更优雅的方法。下面是一些伪代码来说明我的意思。你知道吗

class TreeItem(MPTTModel):
    _save_registry = set()

    ... your model fields go here ...

    def is_save_locked(self):
        return any(p.id in TreeItem._save_registry for p in self.get_parents())

    def save_lock(self):
        TreeItem._save_registry.add(self.id)

    def save_release(self):
        TreeItem._save_registry.remove(self.id)

    def save(self, *args, **kwargs):
        if not self.is_save_locked:
             self.save_lock()
             ... do things only original save should do ...
             self.save_release()
        ... do things every save should do ...
        return super(TreeItem, self).save(*args, **kwargs)

相关问题 更多 >