La cuenta social de django-allauth se conecta a la cuenta existente al iniciar sesión

Tengo un modelo de usuario personalizado y estoy usando django-allauth para el registro social y el inicio de sesión. Estoy intentando conectar a un usuario existente con una nueva cuenta social cuando un usuario inicia sesión con una cuenta social que ya se ha registrado mediante correo electrónico. He encontrado este enlace .

def pre_social_login(self, request, sociallogin): user = sociallogin.account.user if user.id: return try: customer = Customer.objects.get(email=user.email) except Customer.DoesNotExist: pass else: perform_login(request, customer, 'none') 

Pero recibo un error cuando bash iniciar sesión a través de una cuenta social.

 RelatedObjectDoesNotExist at /accounts/facebook/login/callback/ SocialAccount has no user. 

Cualquier ayuda será apreciada.

También estoy al tanto del problema de seguridad en esto. Pero todavía quiero probar esto.

Logré que esto funcionara cambiando un poco el código del adaptador.

adaptador.py

 from allauth.socialaccount.adapter import DefaultSocialAccountAdapter class MySocialAccountAdapter(DefaultSocialAccountAdapter): def pre_social_login(self, request, sociallogin): user = sociallogin.user if user.id: return try: customer = Customer.objects.get(email=user.email) # if user exists, connect the account to the existing account and login sociallogin.state['process'] = 'connect' perform_login(request, customer, 'none') except Customer.DoesNotExist: pass 

Si se hace una subclase de DefaultSocialAccountAdapter , debemos especificar SOCIALACCOUNT_ADAPTER = 'myapp.my_adapter.MySocialAccountAdapter' en el archivo settings.py

Encontré la siguiente solución aquí que también verifica que las direcciones de correo electrónico estén verificadas.

 from allauth.account.models import EmailAddress def pre_social_login(self, request, sociallogin): # social account already exists, so this is just a login if sociallogin.is_existing: return # some social logins don't have an email address if not sociallogin.email_addresses: return # find the first verified email that we get from this sociallogin verified_email = None for email in sociallogin.email_addresses: if email.verified: verified_email = email break # no verified emails found, nothing more to do if not verified_email: return # check if given email address already exists as a verified email on # an existing user's account try: existing_email = EmailAddress.objects.get(email__iexact=email.email, verified=True) except EmailAddress.DoesNotExist: return # if it does, connect this new social login to the existing user sociallogin.connect(request, existing_email.user) 

Si prefiere omitir el paso de verificación, creo que esta solución sigue siendo un poco mejor:

 def pre_social_login(self, request, sociallogin): user = sociallogin.user if user.id: return if not user.email: return try: user = User.objects.get(email=user.email) # if user exists, connect the account to the existing account and login sociallogin.connect(request, user) except User.DoesNotExist: pass