2015-03-06 16 views
7

Mam niestandardowy model użytkownika i używam django-allauth do społecznej rejestracji i logowania. Próbuję połączyć istniejącego użytkownika z nowym kontem społecznościowym, gdy użytkownik zaloguje się za pomocą konta społecznościowego, który już zarejestrował się za pomocą poczty e-mail. Znalazłem to link.Konto społecznościowe django-allauth połączyć się z istniejącym kontem przy logowaniu

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') 

Ale pojawia się błąd podczas próby zalogowania się za pośrednictwem konta społecznościowego.

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

Każda pomoc zostanie doceniona.

Jestem również świadomy kwestii bezpieczeństwa w tym. Ale nadal chcę tego spróbować.

+0

Czytałaś sekcję dotyczącą modeli użytkowników zwyczaj i Django allauth? http://django-allauth.readthedocs.org/en/latest/advanced.html#custom-user-models – petkostas

Odpowiedz

15

Udało mi się to zrobić działając trochę zmieniając kod adaptera.

adapter.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 

Jeśli subclassing DefaultSocialAccountAdapter, musimy określić SOCIALACCOUNT_ADAPTER = 'myapp.my_adapter.MySocialAccountAdapter' w settings.py plik

+0

Gdzie jest klasa Klient? –

+1

Klasy klienta to tylko przykład. Stworzyłem niestandardowy model użytkownika z django's AbstractBaseUser. – anupsabraham

+1

Okay ... Czy możesz również wyjaśnić, czy dokonałeś tej zmiany w kodzie allauth, czy zrobiłeś osobną klasę? –

0

Znalazłem następujące rozwiązanie here który również sprawdza czy adresy e-mail są weryfikowane.

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) 

jeśli wolisz, aby pominąć etap weryfikacji, myślę, że to rozwiązanie jest jeszcze nieco lepiej:

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