Сохранение фотографии Facebook в Django Model (REST Social Oath2)

Этот вопрос касается автоматического сохранения изображений профиля Facebook в модели Django с использованием библиотеки https://github.com/PhilipGarnero/django-rest-framework-social-oauth2.

Изменить: Есть 2 способа решить этот вопрос: сохранить URL-адрес изображения в CharField() или сохраните само изображение, используя ImageField(), Оба решения подойдут.


Вышеупомянутая библиотека позволяет мне создавать и аутентифицировать пользователей, используя токены на предъявителя. У меня есть созданная модель профиля:

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='userprofile')
    photo = models.FileField(blank=True) # OR
    ######################################
    url = 'facebook.com{user id}/picture/'
    photo = models.CharField(default=url)

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

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.userprofile.save()

Который автоматически создает профили пользователей для каждого пользователя. Теперь я хотел бы добавить следующий код, чтобы сохранить фотографию из Facebook. API Facebook требует user id чтобы получить эту картину.

photo = 'https://facebook/{user-id}/picture/'
UserProfile.objects.create(user=instance, photo=photo)

Выше не работает, потому что

1) Я не могу понять, где взять user id от.

2) Изображение не может быть сохранено таким образом, мне нужно преобразовать его в байты или каким-либо другим способом.

2 ответа

Решение

Для этого есть ОЧЕНЬ простое решение. Используйте конвейеры python-social-auth.

То, как работает эта вещь, так же, как middleware, вы можете добавить на странице настроек в SOCIAL_AUTH_PIPELINE раздел функция, которая будет запускаться каждый раз, когда пользователь проходит проверку подлинности с использованием social_django,

Пример:

На странице настроек добавьте следующее:

SOCIAL_AUTH_PIPELINE = (
    'social.pipeline.social_auth.social_details',
    'social.pipeline.social_auth.social_uid',
    'social.pipeline.social_auth.auth_allowed',
    'social.pipeline.social_auth.social_user',
    'social.pipeline.user.get_username',
    'social.pipeline.user.create_user',
    'social.pipeline.social_auth.associate_user',
    'social.pipeline.social_auth.load_extra_data',
    'social.pipeline.user.user_details',
    'home.pipeline.save_profile',
)

смотреть на home.pipeline.save_profileэто новый трубопровод в home.pipeline файл. (Измените его в свою папку пользовательского модуля)

Там (home.pipeline) добавить следующее:

from .models import UserProfile

def save_profile(backend, user, response, *args, **kwargs):
    if backend.name == "facebook":
        UserProfile.objects.create(
            user=user, 
            photo_url=response['user']['picture']
        )

Это пример. Вам нужно изменить его для получения / обновления, если пользователь уже вошел в систему. Также попробуйте поиграть с response аргумент, там могут быть разные данные, которые вы можете использовать там.

И последнее, не забудьте добавить picture Атрибут в ваших настройках:

SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
  'fields': 'id, name, email, picture'
}

http://python-social-auth.readthedocs.io/en/latest/backends/facebook.html

https://godjango.com/122-custom-python-social-auth-pipeline/

https://github.com/python-social-auth/social-app-django

Приведенные выше ответы могут не работать (у меня это не сработало), поскольку URL-адрес профиля facebook больше не работает без токена доступа. Следующий ответ сработал для меня.

      def save_profile(backend, user, response, is_new=False, *args, **kwargs):
    if is_new and backend.name == "facebook":
        # The main part is how to get the profile picture URL and then do what you need to do
        Profile.objects.filter(owner=user).update(
            imageUrl='https://graph.facebook.com/{0}/picture/?type=large&access_token={1}'.format(response['id'],response['access_token']))

добавить в пайплайн в settings.py,

      SOCIAL_AUTH_PIPELINE+ = ('<full_path>.save_profile')
Другие вопросы по тегам