【问题标题】:Django allauth with email as username and multiple sites使用电子邮件作为用户名和多个站点的 Django allauth
【发布时间】:2018-09-16 11:26:18
【问题描述】:

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

我的目标是允许电子邮件地址为 bob@example.com 的用户在 site1.com 上创建一个帐户,并在 site2.com 上创建一个单独的帐户。

为了使用电子邮件身份验证,我需要在设置中将 UNIQUE_EMAIL 设置为 True,但这会阻止已经在一个站点中拥有帐户的用户在另一个站点中创建帐户。

【问题讨论】:

    标签: django django-allauth django-sites


    【解决方案1】:

    我假设您希望允许为您的 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
    

    一种方法如下: - 保留 allauth AUTHENTICATION_METHOD 作为用户名 - 将站点与用户信息一起存储,可能在 UserProfile 中或通过覆盖用户模型。 - 使EmailSite 的组合独一无二。 - 覆盖LoginView 以便用户输入电子邮件;您可以将EmailSite 的组合翻译为唯一用户帐户和用户名;您可以将其传递给 allauth 以执行登录。

    假设您使用网站框架;你的代码看起来像这样:

    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)
    

    然后用自定义登录视图对 LoginView 进行猴子补丁:

    allauth.account.views.LoginView = CustomLoginView

    关于设置站点 FK 和自定义身份验证后端的相关阅读:

    【讨论】:

    • 虽然我认为这可能有效,但在这里做这件事似乎并不正确。强制allauth认为它使用用户名登录似乎有点像黑客攻击,而实际上它使用的是电子邮件。
    • 是的,这是一个 hack。就像我提到的,django 用户模型不会将站点与用户相关联,所以这样做很自然的方式 afaik
    • 这种方法确实有效,但它需要比上面更多的努力。 allauth 代码中有很多地方过滤电子邮件地址,而没有(显然)考虑到站点,因此需要大量覆盖方法,我并不完全相信这是正确的做法。然而,在没有得到安劳斯人的任何回应的情况下,我认为这是唯一真正的选择。
    猜你喜欢
    • 2015-04-27
    • 2015-02-05
    • 2020-10-26
    • 2014-11-20
    • 2011-09-15
    • 2011-04-02
    • 2016-02-09
    • 2012-02-18
    • 2013-07-23
    相关资源
    最近更新 更多