使用django-allauth更改用户电子邮件地址(带/不带验证)

11

我正在使用普通的django-allauth,没有使用任何社交账户。每个用户应该只有一个与其账户关联的电子邮件地址,即用于注册/验证的那个电子邮件地址。我想让我的用户更改这个电子邮件地址。

因此,我的第一个问题是,我应该通过发送验证电子邮件来验证新的电子邮件吗?我的直觉告诉我,最好验证这个新的电子邮件。但我没有真正的理由支持这个想法。

我的第二个问题是,如果我希望进行验证,是否已经在django-allauth中提供了这个过程的支持?我已经看到了EmailView和AddEmailForm。但是,这些都是基于一个账户可以拥有多个电子邮件地址的假设(这不是我想要的)。

谢谢


请查看EmailViewAddEmailForm - elssar
谢谢你,elssar。我刚刚更新了我的问题。 - schacki
2个回答

19

我认为应该验证新的电子邮件地址。如果您的应用程序发送周期性的电子邮件,您不希望向用户输入的任何电子邮件地址发送大量的电子邮件。

我的做法是允许多个电子邮件地址,直到第二个电子邮件地址得到验证。然后,按照elssar的建议,监听django-allauth的email_confirmed信号。一旦地址得到验证,将新的电子邮件地址设置为主电子邮件地址,然后删除任何先前的EmailAddess。以下是我最终采取的简化示例:

模型:

from django.dispatch import receiver
from allauth.account.models import EmailAddress
from allauth.account.signals import email_confirmed

class CustomUser(models.Model):
    ...
    def add_email_address(self, request, new_email):
        # Add a new email address for the user, and send email confirmation.
        # Old email will remain the primary until the new one is confirmed.
        return EmailAddress.objects.add_email(request, self.user, new_email, confirm=True)

@receiver(email_confirmed)
def update_user_email(sender, request, email_address, **kwargs):
    # Once the email address is confirmed, make new email_address primary.
    # This also sets user.email to the new email address.
    # email_address is an instance of allauth.account.models.EmailAddress
    email_address.set_as_primary()
    # Get rid of old email addresses
    stale_addresses = EmailAddress.objects.filter(
        user=email_address.user).exclude(primary=True).delete()

浏览次数:

def update_user_details(request):
    user = request.user
    new_email = request.POST.get('new_email')
    user.custom_user.add_email_address(request, new_email)
    ...

也许我漏掉了什么,但在我看来,要实现一个单一的电子邮件地址,你所需要做的就是导入和从@receiver…models下的代码。也就是说,你不需要在views中使用CustomUser模型或代码。 - typonaut
@typonaut 你可以通过更少的工作量拥有一个单一的电子邮件地址,但这个解决方案也允许你更新电子邮件地址,同时防止用户保留多个电子邮件。 - gatlanticus

3
有几种方法可以解决这个问题。一种方法是监听 email_confirmed 信号处理程序,并编写一个函数来检查用户帐户是否有两个与其关联的 EmailAccount 对象,如果是,则删除其他 EmailAccount 对象。
另一种方法是在设置中设置 EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URLEMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL,并让相关视图删除额外的电子邮件地址(如果存在)。
还有一种方式就是重写 EmailView 和/或 AddEmailForm,让它们执行所需操作。
要在没有确认的情况下更改电子邮件,您只需让视图调用 EmailAddress.change 方法即可。

当我们使用 EmailAddress.change 时,应该触发 email_changed 信号吗?如果我错了,请纠正我。 - Prakhar
1
@Prakhar 我已经很久没有使用allauth了,所以我可能会错,但是从快速扫描代码来看,当用户将他们的主要电子邮件从一个电子邮件对象更改为另一个时,email_changed信号被触发。 EmailAddress.change会更改同一对象中电子邮件的值。 - elssar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接