Reputation: 3329
I'm using Django Social Auth (v0.7.22) for registering users via Facebook, and that is working OK.
My doubt is how to collect extra data for new users:
**kwargs
)?My pipeline looks like:
SOCIAL_AUTH_PIPELINE = (
'social_auth.backends.pipeline.social.social_auth_user',
'social_auth.backends.pipeline.misc.save_status_to_session',
## My customs ...
'myapp.pipeline.load_data_new_user',
'myapp.pipeline.handle_new_user',
'myapp.pipeline.username',
##
'social_auth.backends.pipeline.user.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',
)
The first custom function just collect the Facebook profile picture:
def load_data_new_user(backend, response, user, *args, **kwargs):
if user is None:
if backend.name == "facebook":
try:
url = "http://graph.facebook.com/%s/picture?width=200&height=200&redirect=false" % response['id']
data = json.loads(urllib2.urlopen(url).read())['data']
return {'avatar': data}
except StandardError:
return {'avatar': None}
else:
raise ValueError()
My doubts:
user
is None
for detecting new users (not sure if it's OK to assume that). **kwargs
instead of use sessions, is it OK? When should I use session.The other custom functions are based on the Matias Aguirre example, and use sessions for storing the username of new users.
def handle_new_user(request, user, *args, **kwargs):
if user is None and not request.session.get('saved_username'):
return HttpResponseRedirect('/form/')
def username(request, user, *args, **kwargs):
if user is not None:
username = user.username
else:
username = request.session.get('saved_username')
return {'username': username}
So, I'm not sure when to use sessions or the "correct idiom" for resolve my problem. Thanks in advance.
Upvotes: 6
Views: 7326
Reputation: 3329
Matias Aguirre (django socialauth creator) gently answered my question in the DSA google mail list
His answer:
Collecting the data is easy as you saw, but where to put it depends on your project, what you plan to do with the data, and where you expect it to be available. For example, if you plan to put the avatar image on a user profile model, then you should get the profile for the current user and store it there, if you use a custom user with an avatar_url field, then you should fill that field after the user was created, if you plan to download the image and store it local to the server using the username (id, etc) as the filename, then just do it that way too.
The session is usually used as a mechanism of communication with a view.
Regarding the "user is new", there's a flag "is_new" set to True/False when the user is new or not, but it's not updated until the "create_user" is called.
The pipeline entry "save_status_to_session" should be placed before the method that breaks the pipeline flow, in your case handle_new_user.
Thanks everyone.
Upvotes: 6
Reputation: 15370
I was having a similar problem trying to get extra data with Tumblr and Instagram until I found this article.
There seems to be two ways to popular extra_data
when a user is created / associated:
This is the easiest way for many pieces of data, but may not be accessible depending on the circumstances. There is a brief mention of it on the OAuth page in the docs.
For example, in your settings file:
FACEBOOK_EXTRA_DATA = [('<actual field from FB>', '<your alias>')]
However, it doesn't appear that the various backends return consistent values, so I had to debug social_auth.backends.pipeline.social.load_extra_data
in order to find what fields were accessible. Sometimes, the individual backend describes which fields are available (e.g. see Facebook Backend), or the API documentation, but the most reliable way is to step through their code.
As you've started, you can define a custom function and hook it into the pipeline. From the linked article (and slightly modified):
def get_user_avatar(backend, details, response, social_user, uid,\
user, *args, **kwargs):
url = None
if getattr(backend, 'name', None) == 'facebook':
url = "http://graph.facebook.com/%s/picture?type=large" % response['id']
if url:
# Save the image somewhere, or just use the URL
avatar = url
social_user.extra_data['avatar'] = avatar
social_user.save()
In either case, once you've done that, the extra data is available via social_user.extra_data['your_field']
. Hope that helps.
From my understanding, unless you are using django-socialauth
for account login, the pipeline is only run on the initial association, so the user will always be new at that point. Beyond that, I'm not 100% sure.
Upvotes: 0