Skip to content

Instantly share code, notes, and snippets.

@revolunet
Last active January 14, 2021 05:58
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save revolunet/5104376 to your computer and use it in GitHub Desktop.
Save revolunet/5104376 to your computer and use it in GitHub Desktop.
Sample custom pipeline for django-social-auth and Facebook backend. Goal is to ask more info to the user before creating the account and the related Customer model.
# settings.py
FACEBOOK_EXTENDED_PERMISSIONS = ['email', 'user_birthday', 'user_location']
SOCIAL_AUTH_PIPELINE = (
'social_auth.backends.pipeline.social.social_auth_user',
'social_auth.backends.pipeline.user.get_username',
'social_auth.backends.pipeline.misc.save_status_to_session',
'web.facebook.check_registered',
'social_auth.backends.pipeline.user.create_user',
'web.facebook.check_profile',
'social_auth.backends.pipeline.social.associate_user',
'social_auth.backends.pipeline.social.load_extra_data',
'social_auth.backends.pipeline.user.update_user_details'
)
# facebook.py
def check_registered(*args, **kwargs):
''' check that the user completed the registration form '''
log.info('check if user registered')
request = kwargs.get('request')
has_registered = request.session.get('register_data')
if has_registered:
log.info('user registration complete')
return None
return redirect('register')
def check_profile(*args, **kwargs):
''' check that the user have an existing profile '''
log.info('check if user profile exists')
request = kwargs.get('request')
customer_data = request.session.get('register_data')
customer, is_new = models.Customer.objects.get_or_create(user=kwargs.get('user'), defaults=customer_data)
return {
'customer':customer
}
class RegisterForm(forms.ModelForm):
''' simple ModelForm with some additionnal fields (birthdate, gender, city...) '''
class Meta:
model = models.Customer
exclude = ('user',)
def register_form(request):
''' when not registered, user is redirected to this form '''
request.session['register_data'] = False
pipeline_session_key = setting('SOCIAL_AUTH_PARTIAL_PIPELINE_KEY', 'partial_pipeline')
form = None
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
# form is valid, go next step
request.session['register_data'] = form.cleaned_data
backend = request.session[pipeline_session_key]['backend']
return redirect('socialauth_complete', backend=backend)
template_data = {}
if not form:
# initiate form with facebook values if any
user_data = request.session.get(pipeline_session_key, {}).get('kwargs', {}).get('response', {})
if not user_data:
return redirect('socialauth_complete', backend=backend)
initial_values = {
'email': user_data.get('email'),
'first_name': user_data.get('first_name'),
'last_name': user_data.get('last_name'),
'city': user_data.get('location', {}).get('name', '').split(',')[0],
'birthdate': user_data.get('birthday'),
'gender': 'Mme' if user_data.get('gender') == 'female' else 'M',
}
template_data['form_values'] = initial_values
form = RegisterForm(initial=initial_values)
tpl = Template('''
<form action="" method="POST">
{% csrf_token %}
<p>
{{ form.as_ul }}
</p>
<input type="submit" value="Send" />
</form>''')
template_data['form'] = form
return HttpResponse(tpl.render(RequestContext(request, template_data)))
@max107
Copy link

max107 commented Aug 5, 2013

thanks!

@matlex
Copy link

matlex commented Dec 4, 2015

Thanks a lot!

@xelawafs
Copy link

Is this still supported with the migrations that happened with the project?

@Sashkow
Copy link

Sashkow commented Sep 14, 2018

How to run it, where is facebook.py?

@nbomanji-r7
Copy link

nbomanji-r7 commented Feb 24, 2019

Why am I getting this error can someone please help me out

The requested URL /oauth/complete/github/login.views.require_email was not found on this server.

This is my code for asking a user to register his email after github oauth. It works perfectly till the partial method. Once it transfers to views.py that is where the error occurs

settings.py

SOCIAL_AUTH_PIPELINE = (
    'social_core.pipeline.social_auth.social_details',
    'social_core.pipeline.social_auth.social_uid',
    'social_core.pipeline.social_auth.auth_allowed',
    'hello_world_blog.pipeline.collect_password',
    'social_core.pipeline.social_auth.social_user',
    'social_core.pipeline.social_auth.associate_user',
    'social_core.pipeline.social_auth.load_extra_data',
    'social_core.pipeline.user.user_details',
)

pipeline.py

@partial
def collect_password(strategy, backend, request, details, *args, **kwargs):
    print("partial called")
    return redirect('login.views.require_email')

login.views

def require_email(request):
    print("called require_email view")
    return render(request, 'registration/email.html', args)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment