【问题标题】:Handling duplicate email address in django allauth在 django allauth 中处理重复的电子邮件地址
【发布时间】:2018-01-13 20:10:06
【问题描述】:

我想做什么?

我正在尝试通过以下步骤避免重复的电子邮件地址:

  1. 在用户从社交帐户登录我的网站之前,我会检查电子邮件地址是否已经存在。
  2. 如果没有,则登录用户,否则检查以下步骤。

    • 检查注册用户的提供者是否与尝试登录的用户匹配。

    • 如果否,则不允许用户登录,否则登录用户。

有什么问题?

我收到以下错误:

错误:AttributeError at /accounts/twitter/login/callback/ 'QuerySet' object has no attribute 'profile'

我的代码:

views.py:

@receiver(pre_social_login)
def handleDuplicateEmail(sender, request, sociallogin, **kwargs):
    if sociallogin.account.provider == 'facebook' or sociallogin.account.provider == 'twitter': 
        email_address = sociallogin.account.extra_data['email'] # get email address from fb or twitter social account.
    else:
        email_address = sociallogin.account.extra_data['email-address']  # Get email from linkedin social account.
    users = User.objects.all().filter(email=email_address) # This line is problematic
    if users:  
        if not (users.profile.provider == sociallogin.account.provider):    # Different user is trying to login with already existing user's email address.         
            response = 'Your social account email address is already registered to some account. Please choose a different one.'
            raise ImmediateHttpResponse(render(request, 'index.html', {'type': True, 'response': response}))    # redirect to index template with error message.

models.py:

class Profile(models.Model):
     user = models.OneToOneField(User, related_name='profile', on_delete=models.CASCADE)        
     provider = models.CharField(max_length=256, blank=True, null=True) # for storing name of provider used to login with.

编辑:

由于 FacebookTwitterLinkedin 让用户可以选择使用他们的电话号码或电子邮件地址登录,如果他们选择电话号码,那么由于用户没有与之关联的电子邮件地址来处理这种情况,因此我更新了我的代码,如下所示:

if sociallogin.account.provider == 'facebook' or sociallogin.account.provider == 'twitter': 
    try:
        email_address = sociallogin.account.extra_data['email']
    except:
        email_address = None # If social account was created on phone number for facebook & twitter
else:
    try:
        email_address = sociallogin.account.extra_data['email-address'] 
    except:
        email_address = None # If social account was created on phone number or linkedin
if email_address:        
    users = User.objects.all().filter(email=email_address)
    if users.exists():
        ...
else:
    response = 'You have not provided an email address in your social account. Please register as local user or use a different social account.'
    raise ImmediateHttpResponse(render(request, 'index.html', {'type': True, 'response': response}))    

【问题讨论】:

    标签: django django-allauth


    【解决方案1】:

    users = User.objects.all().filter(email=email_address) 返回一个QuerySet,所以你不能只调用.profile。理论上,这个查询可以返回多个User 对象。但它也可能包含 0 个对象(这更有可能)。

    所以你需要处理这些情况:

    if users.exists():
        user = users.first()  # assuming there will always only be one user
        if not user.profile.provider == sociallogin.account.provider:
            etc...
    

    if users.exists():
        for user in users:
             if not user.profile.provider == sociallogin.account.provider:
                 etc...
                 break
    

    【讨论】:

    • 感谢它的工作:)。顺便说一句,我想知道这是否是处理重复电子邮件地址的正确方法?有什么方法可以让我简单地获取注册用户的提供者,而不是将其显式存储在配置文件模型中。 ?
    • 我又遇到了一个问题。如果重复电子邮件持有人的用户名不匹配,那么我的代码将失败。简单来说,重复电子邮件的用户名也必须匹配,否则我会得到一个空的 <QuerySet []> 我将如何解决这个问题?
    • 问题已解决。似乎linkedin不会将电子邮件地址转换为小写。所以我不得不将电子邮件地址转换为小写。那么这是处理重复电子邮件的正确方法吗?
    • @Ahtisham 我有点困惑。我也使用 django-allauth 并且不必写任何东西来检查重复的电子邮件,这是由 django-allauth 自动处理的。如果您设置了ACCOUNT_EMAIL_REQUIRED = True,如果用户没有通过linkedin 提供电子邮件地址,则会有一个使用allauth.socicalaccount.forms.SignupForm 的额外注册步骤来提示用户输入电子邮件地址。它会检查独特的电子邮件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 2021-10-26
    • 2016-02-09
    • 2021-08-29
    • 2016-07-02
    • 2014-11-09
    • 2019-12-17
    相关资源
    最近更新 更多