14

I use django-rest-auth and django-allauth about user registration/login using user's Facebook profile.

Now, I can take some standard information from Facebook (default for all auth).

Is possible to retrieve also list of avatar-pictures? How can make it in allAuth?

Safari
  • 11,437
  • 24
  • 91
  • 191

3 Answers3

28

If you want to get avatar pictures in a django template:

<img src="{{ user.socialaccount_set.all.0.get_avatar_url }}" />

Is that what you were trying to do?

medullaskyline
  • 389
  • 2
  • 5
  • Any idea how to cache those? It would be expensive to call them in realtime every time a page loads.. – Özer Mar 15 '17 at 01:25
  • @ÖzerS. can you please elaborate? How is it expensive? Wouldn't it be more expensive to cache them on your own server then just have facebooks servers deliver? – distractedhamster May 28 '17 at 04:27
  • @Daggepagge every time someone opens up a page that uses this snippet, your server will contact Facebook and get the data. That usually takes a second or so, so your page will not render until it got the data (if not ajax). Caching only stored the url once and retrives it directly from your server, leaving out the 1 sec delay you would need to contact facebook. – Özer May 29 '17 at 14:57
  • 2
    @ÖzerS. This is incorrect. Calling `get_avatar_url` only formats a URL that you can pass to an `img` tag. It does not do some kind of HTTP request. It will load the image just like any other normal image. – Marcus Lind Jan 05 '19 at 07:46
  • How would you loop through this that would show the avatars/profile pictures on to other users? – Vicente Antonio G. Reyes Dec 06 '19 at 06:37
  • I know it's so late to answer this question, but if you are still interested I have an idea. You customize your user model to have avatar field. then if social account connects it can fetch that URL and make it yourusermodel.avatar. that way you will get URL from your own server. @ÖzerS. – Kenan Apr 01 '20 at 18:01
12

Let me quickly described how i did it (using all_auth and rest_auth).

Basically, 'allauth => socialaccount' provide user_signed_up and user_logged_in signals. So you need to catch them and get sociallogin object's extra data and populate your avatar_url.

Step-1: Create a UserProfile model: (to store avatar_url)

#models.py
try:
    from django.utils.encoding import force_text
except ImportError:
    from django.utils.encoding import force_unicode as force_text

class UserProfile(models.Model):
    user = models.OneToOneField(User, primary_key=True, verbose_name='user', related_name='profile')
    avatar_url = models.CharField(max_length=256, blank=True, null=True)

    def __str__(self):
        return force_text(self.user.email)

    class Meta():
        db_table = 'user_profile'

Step-2: Catch 'user_signed_up' signal and populate `avatar_url'

# signals.py

from allauth.account.signals import user_signed_up, user_logged_in

@receiver(user_signed_up)
def social_login_fname_lname_profilepic(sociallogin, user):
    preferred_avatar_size_pixels=256

    picture_url = "http://www.gravatar.com/avatar/{0}?s={1}".format(
        hashlib.md5(user.email.encode('UTF-8')).hexdigest(),
        preferred_avatar_size_pixels
    )

    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':
            f_name = sociallogin.account.extra_data['first_name']
            l_name = sociallogin.account.extra_data['last_name']
            if f_name:
                user.first_name = f_name
            if l_name:
                user.last_name = l_name

            #verified = sociallogin.account.extra_data['verified']
            picture_url = "http://graph.facebook.com/{0}/picture?width={1}&height={1}".format(
                sociallogin.account.uid, preferred_avatar_size_pixels)

        if sociallogin.account.provider == 'google':
            f_name = sociallogin.account.extra_data['given_name']
            l_name = sociallogin.account.extra_data['family_name']
            if f_name:
                user.first_name = f_name
            if l_name:
                user.last_name = l_name
            #verified = sociallogin.account.extra_data['verified_email']
            picture_url = sociallogin.account.extra_data['picture']

    user.save()
    profile = UserProfile(user=user, avatar_url=picture_url)
    profile.save()        

Hope this will help you.

Jadav Bheda
  • 5,031
  • 1
  • 30
  • 28
  • 2
    Its show error: `Signal receivers must accept keyword arguments (**kwargs).` Function prototype should be like this: `social_login_fname_lname_profilepic(sociallogin, user, **kwargs):` – Ahtisham Jan 09 '18 at 13:51
0

In case you don't want to use Django Signals, you can extend DefaultSocialAccountAdapter from allauth.socialaccount.adapter and override populate_user:

from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
from allauth.account.utils import user_field


class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):
    def populate_user(self, request, sociallogin, data):
        user = super().populate_user(request, sociallogin, data)
        try:
            picture = sociallogin.account.extra_data['picture']
            user_field(user, "profile_photo", picture)
        except (KeyError, AttributeError):
            pass
        return user

Note you should also change DefaultSocialAccountAdapter in settings.py:

SOCIALACCOUNT_ADAPTER = 'some_app.path.to.CustomSocialAccountAdapter'