【问题标题】:Best way to send a mail in Django Model when a user's password has been changed?更改用户密码时在 Django 模型中发送邮件的最佳方式?
【发布时间】:2021-04-22 04:52:32
【问题描述】:

我今年是 python 和 django 的新手,我只是想知道如何在更新密码后通过send_mail 向用户发送简单的邮件? 我已经通过 pre_save 的 Signals 进行了管理,但是我不想让用户等到邮件发送完毕(据我所知,我无法解决这个问题)。使用post_save,无法查询之前的状态。

如果我给出以下用户模型,这里最好的方法是什么?

class User(AbstractBaseUser):

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    email = models.EmailField(verbose_name="email address", max_length=255, unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []

    # Tells Django that the UserManager class defined above should manage
    # objects of this type
    objects = UserManager()

    def __str__(self):
        return self.email

    class Meta:
        db_table = "login"

我已经使用 pre_save 信号进行了设置,但由于延迟,这对我来说不是解决方案:

@receiver(pre_save, sender=User)
def on_change(sender, instance: User, **kwargs):
    if instance.id is None:
        pass
    else:
        previous = User.objects.get(id=instance.id)
        if previous.password != instance.password:
            send_mail(
                "Your password has changed",
                "......",
                "info@examplpe.com",
                [previous.email],
                fail_silently=False,
            )

提前致谢

【问题讨论】:

  • 您可以覆盖表单的保存方法。
  • 你能给我举个例子吗?我对这种方法没有经验。
  • 由于用户以外的其他人更改了密码(通过管理员后端或类似方式),您需要发送此邮件是否正确?因为否则,您应该通过用户更改密码的视图来执行此操作。

标签: python python-3.x django django-models django-signals


【解决方案1】:

如果您使用的是自定义模型,您可能可以通过调用 set_password() 在实例上设置标志,然后检测其在信号中的存在。

试试这个例子:

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.db.models.signals import post_save


class User(AbstractBaseUser, PermissionsMixin):
    
    ...
    
    def set_password(self, password):
        super(User, self).set_password(password)
        self._set_password = True

    @classmethod
    def user_changed(cls, sender, instance, **kwargs):
        if getattr(instance, '_set_password', False):
            # Send your mail


post_save.connect(User.user_changed, sender=User)

【讨论】:

    【解决方案2】:

    您可以覆盖 User 模型的保存方法。以下是来自docs 的示例以及检查来自SO 的更改值:

    class User(AbstractBaseUser):
        ...
    
        __original_password = None
    
        def __init__(self, *args, **kwargs):
            super(User, self).__init__(*args, **kwargs)
            self.__password = self.password
    
        def save(self, *args, **kwargs):
            if self.password != self.__original_password:
                notify_user_of_password_change()
            super().save(*args, **kwargs)  # Call the "real" save() method.
    

    【讨论】:

      猜你喜欢
      • 2012-10-25
      • 2012-11-14
      • 2010-11-01
      • 1970-01-01
      • 2010-11-12
      • 2015-04-08
      • 1970-01-01
      • 2020-01-14
      • 1970-01-01
      相关资源
      最近更新 更多