Django-social auth KeyError

I get a KeyError in my partial pipeline when I try to sign up for Twitter accounts while facebook accounts are working fine. This is weird because the same function works great with facebook users.

The error message looks like this:

KeyError at / myapp / 'Partial_pipeline'

in 'myapp_auth_form' and my code is:

settings.py

SOCIAL_AUTH_ENABLED_BACKENDS=('facebook','twitter',)
SOCIAL_AUTH_DEFAULT_USERNAME='new_social_auth_user'

...

TWITTER_CONSUMER_KEY = 'mytwitterconsumerkey'
TWITTER_CONSUMER_SECRET = 'mytwitterconsumersecret'

LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/'
LOGIN_ERROR_URL = '/login-error/'

SOCIAL_AUTH_PIPELINE = (
    'social_auth.backends.pipeline.social.social_auth_user',
    'social_auth.backends.pipeline.misc.save_status_to_session',
    'myapp.pipeline.has_email',
    'myapp.pipeline.check_by_email',
    'myapp.pipeline.redirect_to_form',
    'myapp.pipeline.get_username',
    'myapp.pipeline.create_user',
    'social_auth.backends.pipeline.social.associate_user',
    'social_auth.backends.pipeline.social.load_extra_data',
    'social_auth.backends.pipeline.user.update_user_details'
)

      

myapp.pipeline

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

from social_auth.models import UserSocialAuth
from registration.models import UserProfile


def has_email(details, user=None, *args, **kwargs):
    """Check if email is provided and ask for it otherwise
    """
    if user:
        return None

    email = details.get('email')
    if email:
        kwargs['request'].session['saved_email'] = email
    else:
        session = kwargs['request'].session
        email = session.get('saved_email')

    if not email:
        return HttpResponseRedirect(reverse('myapp_email_form'))

def check_by_email(details, user=None, user_exists=UserSocialAuth.simple_user_exists, *args, **kwargs):
    """Check if there user with same email address and ask for its password to associate
    """
    if user:
        return None

    session = kwargs['request'].session

    email = session.get('saved_email')

    if email:
        if user_exists(username=email):
            return HttpResponseRedirect(reverse('myapp_auth_form'))

def redirect_to_form(*args, **kwargs):
    """Redirect to get password if user is None
    """
    session = kwargs['request'].session
    if not session.get('saved_password') and not session.get('saved_nickname') and not session.get('saved_sex') and kwargs.get('user') is None:
        return HttpResponseRedirect(reverse('social_auth_form'))

def get_username(details, user=None, *args, **kwargs):
    """Return an username for new user. Return current user username
    if user was given.
    Returns email address since myapp uses email for username
    """
    if user:
        return {'username': user.username}

    username = details.get('email') or ''

    return {'username': username}

def create_user(backend, details, response, uid, username, user=None, *args, **kwargs):
    """Create user and user profile. Depends on get_username pipeline."""
    if user:
        return {'user': user}
    if not username:
        return None

    request = kwargs['request']

    password = request.session.get('saved_password') or ''
    user = UserSocialAuth.create_user(username=username, email=username, password=password)

    nickname = request.session.get('saved_nickname') or ''
    sex = request.session.get('saved_sex') or 'F'
    profile = UserProfile.objects.create(user = user, nickname = nickname, sex = sex)

    referee_nickname = request.session.get('saved_referee') or False
    # if there was a recommender
    if referee_nickname:
        try:
            referee_profile = UserProfile.objects.get(nickname=referee_nickname)
            profile.referee = referee_profile.user
            profile.save()
        except UserProfile.DoesNotExist:
            pass

    return {
        'user': user,
        'is_new': True
    }

      

views.py

from social_auth.utils import setting
from django.contrib.auth import authenticate, login

def myapp_email_form(request):
    # if user is logged in already, redirect the user to home
    if request.user.is_authenticated():
        if request.GET.get('mobile', False):
            return HttpResponseRedirect(reverse('m_home'))
        return HttpResponseRedirect(reverse('home'))
    """ If email is unprovided, ask for it
    """
    if request.method == 'POST':
        form = EmailForm(request.POST)

        if form.is_valid():
            email = form.cleaned_data['email']

            name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')
            request.session['saved_email'] = email
            backend = request.session[name]['backend']
            return redirect('socialauth_complete', backend=backend)
    else:
        form = EmailForm()
        email = request.session.get('saved_email') or ''

    variables = RequestContext(request, {
        'form': form,
        'email': email,
    })

    if request.is_mobile or request.GET.get('mobile', False):
        return render_to_response('mobile/registration/social/email_form.html', variables, context_instance=RequestContext(request))

    return render_to_response('.../email_form.html', variables, context_instance=RequestContext(request))

def myapp_auth_form(request):
    # if user is logged in already, redirect the user to home
    if request.user.is_authenticated():
        if request.GET.get('mobile', False):
            return HttpResponseRedirect(reverse('m_home'))
        return HttpResponseRedirect(reverse('home'))
    """ If user email is already registered to myapp, ask user for its password
    """
    if request.method == 'POST':
        form = LoginForm(request.POST)

        if form.is_valid():
            email = form.cleaned_data['username']
            user = authenticate(username=email, password=form.cleaned_data['password'])

            if user is not None:
                if user.is_active:
                    login(request, user)

                    name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')
                    request.session['saved_user'] = user
                    ############################################
                    backend = request.session[name]['backend'] #<- I'm getting the KeyError at this point
                    ############################################
                    return redirect('socialauth_complete', backend=backend)
                else:
                    return HttpResponseRedirect(reverse('inactive_user'))
            else:
                form.non_field_errors = _('A user with such email and password does not exist.')
    else:
        form = LoginForm()
        email = request.session.get('saved_email') or ''

    variables = RequestContext(request, {
        'form': form,
        'email': email,
    })

    if request.is_mobile or request.GET.get('mobile', False):
        return render_to_response('mobile/registration/social/auth_form.html', variables, context_instance=RequestContext(request))

    return render_to_response('.../auth_form.html', variables, context_instance=RequestContext(request))

def social_auth_form(request):
    # if user is logged in already, redirect the user to home
    if request.user.is_authenticated():
        if request.GET.get('mobile', False):
            return HttpResponseRedirect(reverse('m_home'))
        return HttpResponseRedirect(reverse('home'))
    """ Remedy form taking missing information during social authentication
    """
    nickname = ''
    sex = 'F'

    if request.method == 'POST':
        form = SocialRegistrationForm(request.POST)

        if form.is_valid():
            nickname = form.cleaned_data['nickname']
            sex = form.cleaned_data['sex']

            name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')
            request.session['saved_nickname'] = nickname
            request.session['saved_sex'] = sex
            request.session['saved_password'] = form.cleaned_data['password1']
            backend = request.session[name]['backend']
            return redirect('socialauth_complete', backend=backend)
    else:
        form = SocialRegistrationForm()

        nickname = request.session.get('saved_username') or ''
        sex = request.session.get('saved_gender') or 'F'

        if sex == 'male':
            sex = 'M'
        elif sex == 'female':
            sex = 'F'

    variables = RequestContext(request, {
        'form': form,
        'nickname': nickname,
        'sex': sex,
    })

    if request.is_mobile or request.GET.get('mobile', False):
        return render_to_response('mobile/registration/social/social_form.html', variables, context_instance=RequestContext(request))

    return render_to_response('.../auth_form.html', variables, context_instance=RequestContext(request))

      

+3


source to share


2 answers


You need to add 'social_auth.backends.pipeline.misc.save_status_to_session'

before every method that calls the redirect and stops the process. It works with Facebook because Facebook exposes email addresses, but Twitter doesn't. So, add this method before any entry that does the redirect, or call it inside your pipeline code before doing the redirection.



(Just post a comment as an answer so you can select it)

+4


source


You are getting the following error because you are trying to access the session name using this request.session[name]

. This format is supposed to be used when saving the session. To fix this,



name = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')
request.session['saved_user'] = user
############################################
request.session['name'] = name 
backend = request.session.get('name') // this is the session format in getting the data
############################################
return redirect('socialauth_complete', backend=backend)

      

0


source







All Articles