Python-Social-Auth:无法从 Linkedin 保存电子邮件地址值以在管道中使用

Python-Social-Auth: Unable to save email address value from Linkedin for use in pipeline

我已按照此文档中的说明进行操作:https://readthedocs.org/projects/python-social-auth/downloads/pdf/latest/ (page 121) and also from a similar inquiry: python-social-auth partial pipeline can not resume 但我无法从数据库中获取电子邮件地址值,即在我的管道中我不太确定如何从下面的行中获取 kwargs['email'] 上的值。 用户 = User.objects.get(email=kwargs['email'])

看在上帝的份上,任何人都可以帮助我吗?提前致谢!

设置如下:

forms.py

class SocialPasswordForm(forms.Form):
    password = forms.CharField(max_length=32)

views.py

def get_user_password(request):
    print('def post view first')
    if request.method == 'POST':
        print('def post view second')
        form = SocialPasswordForm(request.POST)
        if form.is_valid():
            print('def post view third')
        # because of FIELDS_STORED_IN_SESSION, this will get copied
        # to the request dictionary when the pipeline is resumed
            request.session['local_password'] = form.cleaned_data.get('password')
            #backend = request.session['partial_pipeline']['backend']
        # once we have the password stashed in the session, we can
        # tell the pipeline to resume by using the "complete" endpoint
            print('def post view fourth')
            return redirect(reverse('social:complete', args=('linkedin-oauth2',)))
    else:
        form = SocialPasswordForm()
    return render(request, 'social_signup.html', {'form': form})

 

auth_pipeline.py

from django.shortcuts import redirect
from django.contrib.auth import get_user_model
User = get_user_model()

from social_core.pipeline.partial import partial
# partial says "we may interrupt, but we will come back here again"


@partial
def collect_password(strategy, backend, request, details, *args, **kwargs):
    # session 'local_password' is set by the pipeline infrastructure
    # because it exists in FIELDS_STORED_IN_SESSION
    local_password = strategy.session_get('local_password', None)
    if not local_password:
        # if we return something besides a dict or None, then that is
        # returned to the user -- in this case we will redirect to a
        # view that can be used to get a password
        return redirect('social_signup')
    # grab the user object from the database (remember that they may
    # not be logged in yet) and set their password. (Assumes that the
    # email address was captured in an earlier step.)
    user = User.objects.get(email=kwargs['email'])
    user.set_password(local_password)
    user.save()
    # continue the pipeline
    return

settings.py

SOCIAL_AUTH_PIPELINE = (
    # Get the information we can about the user and return it in a simple
    # format to create the user instance later. In some cases the details are
    # already part of the auth response from the provider, but sometimes this
    # could hit a provider API.
    'social_core.pipeline.social_auth.social_details',

    # Get the social uid from whichever service we're authing thru. The uid is
    # the unique identifier of the given user in the provider.
    'social_core.pipeline.social_auth.social_uid',

    # Verifies that the current auth process is valid within the current
    # project, this is where emails and domains whitelists are applied (if
    # defined).
    'social_core.pipeline.social_auth.auth_allowed',

    # Checks if the current social-account is already associated in the site.
    'social_core.pipeline.social_auth.social_user',

    # Make up a username for this person, appends a random string at the end if
    # there's any collision.
    'social_core.pipeline.user.get_username',

    # Send a validation email to the user to verify its email address.
    # Disabled by default.
    #'social_core.pipeline.mail.mail_validation',

    # Associates the current social details with another user account with
    # a similar email address. Disabled by default.
    'social_core.pipeline.social_auth.associate_by_email',

    # Create a user account if we haven't found one yet.
    'social_core.pipeline.user.create_user',


    # Create the record that associates the social account with the user.
    'social_core.pipeline.social_auth.associate_user',

    # Populate the extra_data field in the social record with the values
    # specified by settings (and the default ones like access_token, etc).
    'social_core.pipeline.social_auth.load_extra_data',

    # Update the user record with any changed info from the auth service.
    'social_core.pipeline.user.user_details',

    #CUSTOM PIPELINE
    'users.auth_pipeline.collect_password',
)

...

SOCIAL_AUTH_FIELDS_STORED_IN_SESSION = ['local_password',]

social_signup.html

{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %}Home{% endblock title %}

{% block content %}

  <form method="POST" class="padding">
    {% csrf_token %}
    {{form|crispy}}
    <button type="submit">Save Password</button>
  </form>

{% endblock content %}

这是错误(很明显我没有存储来自 linkedin 的电子邮件地址)。我该如何存储它?

  File "C:\...\auth_pipeline.py", line 24, in collect_password
    print(kwargs['email'])
KeyError: 'email'

提前致谢。感谢您的宝贵时间。

将我的自定义管道更改为以下解决了问题。

@partial
def collect_password(strategy, backend, request, details, is_new=False, *args, **kwargs):
    # session 'local_password' is set by the pipeline infrastructure
    # because it exists in FIELDS_STORED_IN_SESSION
    local_password = strategy.session_get('local_password', None)
    if is_new:
        if not local_password:
            # if we return something besides a dict or None, then that is
            # returned to the user -- in this case we will redirect to a
            # view that can be used to get a password
            #return redirect(SocialSignUpView)
            return redirect('social_signup')
            # grab the user object from the database (remember that they may
            # not be logged in yet) and set their password. (Assumes that the
            # email address was captured in an earlier step.)
        user = User.objects.get(email=details['email'])
        user.set_password(local_password)
        user.save()
    # continue the pipeline
    return