使用电子邮件作为用户名的Django allauth和多个站点

9

当在多个网站上使用Django allauth身份验证方法设置为“电子邮件”时,是否可以使用它?

我希望允许使用电子邮件地址bob@example.com在site1.com和site2.com创建不同的账户。

为了使用电子邮件认证,需要在设置中将UNIQUE_EMAIL设置为True,但这会阻止已经在一个网站上拥有账户的用户在另一个网站上创建账户。

1个回答

3
我假设您希望允许在Django设置中的每个站点分别注册相同的电子邮件。查看allauth代码后,似乎目前无法实现这一点,可能是因为allauth在用户注册过程中没有考虑站点ID。
class AppSettings(object):

    class AuthenticationMethod:
        USERNAME = 'username'
        EMAIL = 'email'
        USERNAME_EMAIL = 'username_email'

    class EmailVerificationMethod:
        # After signing up, keep the user account inactive until the email
        # address is verified
        MANDATORY = 'mandatory'
        # Allow login with unverified e-mail (e-mail verification is
        # still sent)
        OPTIONAL = 'optional'
        # Don't send e-mail verification mails during signup
        NONE = 'none'

    def __init__(self, prefix):
        self.prefix = prefix
        # If login is by email, email must be required
        assert (not self.AUTHENTICATION_METHOD ==
                self.AuthenticationMethod.EMAIL) or self.EMAIL_REQUIRED
        # If login includes email, login must be unique
        assert (self.AUTHENTICATION_METHOD ==
                self.AuthenticationMethod.USERNAME) or self.UNIQUE_EMAIL

一种实现方法如下: - 将所有auth AUTHENTICATION_METHOD 保持为用户名 - 存储站点信息与用户信息一起,可以通过UserProfile或覆盖User Model实现。 - 使EmailSite的组合唯一。 - 覆盖LoginView以便用户输入电子邮件;您可以将EmailSite的组合翻译为唯一的用户帐户和用户名,然后将其传递给allauth以执行登录。
假设您使用Sites框架,您的代码应该类似于以下内容:
from allauth.account.views import LoginView
from django.core.exceptions import ObjectDoesNotExist


class CustomLoginView(LoginView):

    def get_user():
        email = request.POST.get('email')
        current_site = Site.objects.get_current()
        try:
            user = User.objects.get(email=email, site=current_site)
        except ObjectDoesNotExist:
            pass  # Handle Error: Perhaps redirect to signup 
        return user


    def dispatch(self, request, *args, **kwargs):
        user = self.get_user()
        request.POST = request.POST.copy()
        request.POST['username'] = user.username
        return super(CustomLoginView, self).dispatch(request, *args, **kwargs)

然后使用自定义登录视图monkey-patch LoginView:

allauth.account.views.LoginView = CustomLoginView

有关设置Site FK和自定义认证后端的相关阅读:


1
虽然我认为这可能会起作用,但在这里似乎不是正确的做法。这似乎有点像一个hack,强制allauth认为它正在使用用户名登录,而实际上它正在使用电子邮件。 - bodger
是的,这是一个hack。就像我之前提到的,Django用户模型不会将站点与用户关联起来,所以据我所知没有自然的方法来做到这一点。 - rtindru
2
这种方法确实可行,但需要比上述方法更多的努力。在allauth代码中有很多地方过滤电子邮件地址,而不(显然)考虑站点,因此需要大量覆盖方法,我并不完全相信这样做是正确的。然而,在没有得到来自allauth团队的任何响应的情况下,我认为这是唯一的真正选择。 - bodger

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