Of the several libraries/packages available for setting up social network logins for Django projects, I currently find django-allauth the most complete, with the best docs and the most active development. Doesn’t hurt that the lead dev on the project is super friendly and responsive on StackOverflow!
But not everything about it is intuitive. After wiring up Twitter, Facebook and Google as login providers, I found that first and last names were not being retrieved from the remote services when an account was successfully created. I also, frustratingly, could find only the most oblique references online to how to accomplish this.
There are a couple of ways to go about it – you can either receive and handle the allauth.account.signals.user_signed_up
signal that allauth emits on success, or set up allauth.socialaccount.adapter.DefaultSocialAccountAdapter
, which is also unfortunately barely documented.
I decided to go the signals route. The key to making this work is in intercepting the sociallogin
parameter your signal handler will receive when an account is successfully created. I then installed a breakpoint with import pdb; pdb.set_trace()
to inspect the contents of sociallogin
. Once I had access to those goodies, I was able to post-populate the corresponding User objects in the database.
This sample code grabs First/Last names from Twitter, Facebook or Google; season to taste:
# When account is created via social, fire django-allauth signal to populate Django User record. from allauth.account.signals import user_signed_up from django.dispatch import receiver @receiver(user_signed_up) def user_signed_up_(request, user, sociallogin=None, **kwargs): ''' When a social account is created successfully and this signal is received, django-allauth passes in the sociallogin param, giving access to metadata on the remote account, e.g.: sociallogin.account.provider # e.g. 'twitter' sociallogin.account.get_avatar_url() sociallogin.account.get_profile_url() sociallogin.account.extra_data['screen_name'] See the socialaccount_socialaccount table for more in the 'extra_data' field. ''' if sociallogin: # Extract first / last names from social nets and store on User record if sociallogin.account.provider == 'twitter': name = sociallogin.account.extra_data['name'] user.first_name = name.split()[0] user.last_name = name.split()[1] if sociallogin.account.provider == 'facebook': user.first_name = sociallogin.account.extra_data['first_name'] user.last_name = sociallogin.account.extra_data['last_name'] if sociallogin.account.provider == 'google': user.first_name = sociallogin.account.extra_data['given_name'] user.last_name = sociallogin.account.extra_data['family_name'] user.save()
error on SignUp form for this Code
user_signed_up_() takes exactly 3 arguments (2 given)
Sum Juan – I think you’re referring to the use case where a user peforms a standard login rather than a social login. Yeah, I caught that bug later and failed to update this. Now fixed. Thanks.
Where should i put this receiver method in my project? I am using custom user model.
Raakesh – You can put it wherever makes the most sense for you. In my case, it’s in our custom Profiles model.
Hey,
Where exactly does this happen? After login im redirecting to ‘/home’. So does this happen in the view related to ‘/home’ or is it elsewhere?
Siddarth – that URL is specific to your project – why assume every Django project has a /home URL? The topic is about what happens after the UserSignedIn signal is fired by django-allauth.
Hey, I assumed that this happens in the views of the project. Researching a bit more made me realize it actually happens in the models. Sorry for the earlier question.
Life saver, thank you! Would be interesting if you can do more django-allauth tutorials related to social accounts!
Only the “name” and “id” of the user gets stored in the SocialAccount table. No other fields are fetched from facebook. What could be causing this?