django-allauth: проверьте, зарегистрировался ли пользователь, используя социальную учетную запись

Поэтому я включил в свое приложение django-allauth, и теперь пользователи имеют возможность входить в систему через Instagram. Допустим, у меня есть модель с именем UserProfile, и у нее есть поле

user_avatar = models.ImageField(upload_to='profile_images', blank=True, default=None)

И с этим у меня есть сигнал, который создает профиль пользователя, как только новый пользователь регистрируется:

def create_user_profile(sender, instance, created, **kwargs):
     if created:
         UserProfile.objects.create(user=instance)
 post_save.connect(create_user_profile, sender=User)

Так, обычно, когда пользователь регистрирует user_avatar, является пустым, так как значение по умолчанию установлено как None, теперь я хочу добавить в сигнал (если это правильный способ сделать это), чтобы проверить, создал ли пользователь свою учетную запись, войдя в систему, используя instagram., чтобы пойти и получить свою фотографию профиля и использовать его в user_avatar. Я думаю, что это возможно https://instagram.com/developer/endpoints/users/, но так как я полный нуб в python и django, я не знаю, как именно это сделать.

Так что я нашел этот сигнал из документов Джанго-Аллаута allauth.socialaccount.signals.pre_social_login(request, social_login) так что это говорит о том, что я могу проверить, что пользователь зарегистрировался, используя социальную учетную запись, но как бы я использовал это с моей функцией create_user_profile? Шаги, о которых я подумал, - это сначала создать профиль, который я сделал, а затем проверить, зарегистрировался ли пользователь, используя социальную учетную запись, или нет, если он это сделал, то user_avatar, который использует свое изображение профиля instagram, и если нет, то останется как никто.

И как плюс, я знаю, что могу получить изображение профиля социальной учетной записи пользователя в шаблоне, используя {{user.socialaccount_set.all.0.get_avatar_url}}, но я не хочу делать это с помощью шаблонов, а не делать это с помощью моделей, что является лучшим способом.

Это может выглядеть очень глупо, но я попробовал и попытался что-то придумать (это то, что, как думает новичок, сработает, я думал об этом на макушке, так как понятия не имею, работают ли такие сигналы)

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)
        def pre_social_login(request, social_login):
            user_logged_social = social_login.account.user
            if user_logged_social:
                UserProfile.objects.get(user_avatar=user_logged_social.profile_picture)
            else:
                pass
post_save.connect(create_user_profile, sender=User)

ОБНОВЛЕНИЕ Работает с помощью @bellum! Спасибо!

Вот код, который я использовал:

models.py

class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name="profile")
    user_avatar = models.ImageField(upload_to='profile_images'
                                blank=True,
                                default=None)


    def __unicode__(self):
        return self.user.username

    class Meta:
        verbose_name_plural = "User Profiles"

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)

3utils.py

def download_file_from_url(url):
    # Stream the image from the url
    try:
        request = requests.get(url, stream=True)
    except requests.exceptions.RequestException as e:
        # TODO: log error here
        return None

    if request.status_code != requests.codes.ok:
        # TODO: log error here
        return None

    # Create a temporary file
    lf = tempfile.NamedTemporaryFile()

    # Read the streamed image in sections
    for block in request.iter_content(1024 * 8):

        # If no more file then stop
        if not block:
            break

        # Write image block to temporary file
        lf.write(block)

    return files.File(lf)

class SocialAccountAdapter(DefaultSocialAccountAdapter):
    def save_user(self, request, sociallogin, form=None):
        user = super(SocialAccountAdapter, self).save_user(request, sociallogin, form)

        url = sociallogin.account.get_avatar_url()
        avatar = download_file_from_url(url)
        if avatar:
            profile = user.profile  # access your profile from user by correct name
            profile.user_avatar.save('avatar%d.jpg' % user.pk, avatar)
        return user

settings.py

SOCIALACCOUNT_ADAPTER = 'main.s3utils.SocialAccountAdapter'

Сигнал для создания профиля при регистрации в моих моделях остался прежним, просто добавили SocialAccountAdapter!

1 ответ

Решение

Я сделал ту же задачу для Facebook поставщик. allauth дает возможность достичь этого по-другому. Я думаю, вам не нужно получать аватар каждый раз, когда пользователь входит в вашу систему. Если да, то вы можете переопределить класс следующим образом:

from allauth.socialaccount.adapter import DefaultSocialAccountAdapter

class SocialAccountAdapter(DefaultSocialAccountAdapter):
    def save_user(self, request, sociallogin, form=None):
        user = super(SocialAccountAdapter, self).save_user(request, sociallogin, form)

        url = sociallogin.account.get_avatar_url()

        avatar = download_file_from_url(url)  # here you should download file from provided url, the code is below
        if avatar:
            profile = user.user_profile  # access your profile from user by correct name
            profile.user_avatar.save('avatar%d.jpg' % user.pk, avatar)

        return user

Вы должны добавить эту строку в вашу конфигурацию: SOCIALACCOUNT_ADAPTER = 'path-to-your-adapter.SocialAccountAdapter',

В результате этот код будет вызываться только во время регистрации нового социального аккаунта, получить URL-адрес аватара, загрузить его и сохранить в своем User модель.

import requests
import tempfile

from django.core import files

def download_file_from_url(url):
    # Stream the image from the url
    try:
        request = requests.get(url, stream=True)
    except requests.exceptions.RequestException as e:
        # TODO: log error here
        return None

    if request.status_code != requests.codes.ok:
        # TODO: log error here
        return None

    # Create a temporary file
    lf = tempfile.NamedTemporaryFile()

    # Read the streamed image in sections
    for block in request.iter_content(1024 * 8):

        # If no more file then stop
        if not block:
            break

        # Write image block to temporary file
        lf.write(block)

    return files.File(lf)
Другие вопросы по тегам