Разработка сайта на Django - урок 07 - создание виджета Instagram
Разработка сайта на Django - урок 07 - создание виджета Instagram
В этой статье продолжим создавать блог на Django. В моем шаблоне для блога есть такой блок:
Вывести фото из Instagram намного актуальнее, чем из Flickr.
Реализация будет следующей: фото должны быть уже получены заранее, через API Instagram, чтобы не обращаться за фотками по API каждый раз при загрузке страницы. Фото, которые хотим разместить на сайте, будем добавлять через админку ссылками на посты.
Перед регистрацией приложения в кабинете разработчика, лучше реализовать необходимый функционал в Django заранее. Дело в том, что вам сначала дадут временный токен для работы с API, действует он час, и поэтому, пока вы реализуете функционал, чтобы посмотреть его работу, вам придется получать новый токен. Да и потом нормальный токен действует 60 дней, поэтому лучше добавить функционал в админку Django, чтобы можно было обновлять токен быстрее.
Функционал виджета будет следующий
Функционал я уже подготовил, поэтому буду объяснять под скриншотами.
Сначала я создал приложение inst_widget
Подключаем созданное приложение к проекту
Дальше нам понадобятся следующие библиотеки: Pillow, easy-thumbnails и requests. Так как мы используем виртуальное окружение pipenv, то устанавливать эти библиотеки надо следующими командами:
Теперь в файле models.py в приложении inst_widget создаем модель виджета
Переходим в файл admin.py приложения inst_widget и добавляем модель в админку
То, что перечеркнуто, пока не используем. Смотрим, что получили в админке.
Эта модель имеет имя и хранит токен, который будет использоваться для запросов к API Instagram. Теперь к этой модели необходимо привязать две модели. Одна модель будет отвечать за сохранение ссылок на посты, а вторая модель сохранять изображения из этих постов. По факту эти модели будут связаны через ForeignKey (то есть через внешний ключ).
Данная модель модель будет хранить ссылки на посты.
Эта модель будет хранить изображения.
Обе эти модели основаны на полиморфных связях. То, что необходимо импортировать в models.py для этого
Про полиморфные связи лучше почитать отдельно и попробовать их реализовать самостоятельно. А сейчас добавим в файл admin.py строки, которые у меня были зачеркнуты. Не забываем перед этим всем произвести команды makemigrations и migrate.
В файле admin.py добавлен StackedInline это класс встроенного редактора, который используется для добавления или редактирования записей первичной модели и при этом выводит набор форм вторичной модели. То есть, вторичная модель ListLink будет выводиться в админке при редактировании первичной модели InstagramWidget.
Вместо StackedInline можете попробовать использовать TabularInline и посмотреть результат.
В админке получаем следующее:
Таким образом получаем привязанные модели ссылок и изображений к нашему виджету, и они удобно выводятся списком.
Теперь, при сохранении модели InstagramWidget и добавленных ссылок в модель ListLink должно произойти следующее. Делается запрос по каждой ссылке, которая добавлена в модель. По ссылке скачивается изображение и сохраняется в папку. Так при каждом сохранении изображении мы сохраняем путь до изображения в модель MediaFromInsta. В тип поля ImageField сохраняется просто ссылка до изображения, например, если параметр установлен такой upload_to='instagram', то ссылка на изображение будет instagram/name_image.png.
Этот функционал я не стал выносить отдельно, пока опишу его в файле models.py в приложении inst_widget. Для этого у Django есть сигналы. Сигналы Django предоставляют возможность перехватить процесс фреймворка или приложения и выполнить на основании этого процесса свои процессы.
Для нашего функционала импортируем в файл model.py нашего приложения inst_widget следующее:
Сигнал post_save срабатывает после сохранения модели. Декоратор receiver используется вместо метода connect().
Вот код, который необходимо добавить в models.py
После сохранения модели InstagramWidget начинает работать функция get_media_from_posts. Получаем объект модели widget = InstagramWidget.objects.get(name_widget=instance), которая была сохранена. Потом получаем posts_links = widget.link_post.all() все объекты ссылок на посты. Далее запускаем цикл по ссылкам, чтобы получить img = requests.get(link.link) изображение по ссылке. Получаем имя изображения filename = link.link.split("/")[-1]. Создаем путь dir_media = settings.MEDIA_ROOT + '\\instagram\\' до папки сохранения изображения (я работаю на windows, поэтому у меня путь такой). Открываем файл для записи img_file = open(dir_media + filename, 'wb'). Записываем в файл img_file.write(img.content) контент полученный по ссылке. Дальше создаем путь до изображения, чтобы сохранить в модель fileimage = 'instagram/' + filename. И сохраняем изображение в модель MediaFromInsta.objects.update_or_create(image=fileimage, images_id=widget.id). update_or_create - метод обновляет или создает новую запись, если совпадений в базе не нашлось.
В итоге получаем при сохранении виджета:
Текущий функционал не дописан, так как при обращении к API Instagram будет прилетать JSON, из которого еще нужно вытащить URL изображения. Это допишем чуть ниже, сначала получим токен.
Регистрируем свое приложение в аккаунте разработчика Facebook:
Переходим в аккаунт разработчика Facebook.
Выбираем тип приложения:
Создаем имя приложения:
Выбираем API Instagram Basic Display
Тут появляется возможность настроек, но нам сюда пока не нужно:
Нам нужно сюда
Тут нам понадобятся потом ID app и Secret app (в русском переводе документация, хоть и неплохая, но потом надо не запутаться, куда какой ID вставлять, тем более токен в переводе называют "маркер доступа", и не очень понятно работать с примерами кода). Далее опускаемся вниз.
Необходимо добавить платформу
- 687