Django + API Вконтакте: постимо запису з вкладеннями, отримання списку груп та записів

image

Доброго часу доби, Хабр!

Нещодавно розробляла сайт на python/django і потрібна була можливість використання API Вконтакте. А саме:

• Постинг статей із сайту на сторінку у Вконтакте, а також у вибрані групи (в яких складався адміністратор);
• Можливість прикріплення документів і картинок до записів;
• Отримання списку груп та записів за допомогою оновлюваного скрипта і завантаження всього цього в адмінку django.

Власне, для адміністратора управління цим функціоналом здійснюється через адмінку.

Розповім по кроках реалізацію цього функціоналу.

На першому етапі адміністратору потрібно створити свій додаток у «Вконтакте», а також отримати токен для роботи з API. Для отримання сертифіката я використовую модуль VKAppAuth (посилання на GitHub, там же приклад використання модуля).

Налаштування для отримання зберігаю в окремому файлі і підключаю його в models.py. В models.py додаю поля для «Вконтакте» в модель статті:

photo_vk = models.ImageField(upload_to=photo_vk_path, verbose_name=u ' Прикріпити фото для Вконтакте', max_length = 1000, blank=True)
file_vk = models.FileField(upload_to=files_vk_path, verbose_name=u ' Прикріпити документ для Вконтакте', max_length = 1000, blank=True)
wall_user_vk = models.BooleanField(verbose_name=u ' Відправити на стіну користувача Вконтакте', default=False)
group_vk = models.ManyToManyField(Vk_groups, verbose_name=u ' Відправити у такі групи Вконтакте', blank=True)
group_stat = models.BooleanField(verbose_name=u ' Публікувати запис від імені групи', default=False)


Поле group_vk відображає всі групи «Вконтакте» з таблиці Vk_groups. Код класу Vk_groups в models.py:

class Vk_groups(models.Model):
title = models.CharField(max_length=1000, verbose_name=u ' Назва групи')
gid = models.CharField(max_length=1000, verbose_name=u ' ID групи')
is_closed = models.BooleanField(verbose_name=u ' Закрита група', default=False)
is_admin = models.BooleanField(verbose_name=u ' Користувач є адміністратором', default=False)

def __str__(self):
return self.title.encode('utf8')

class Meta:
verbose_name = "Група Вконтакте"
verbose_name_plural = "Групи Вконтакте"


Також створена модель для записів «Вконтакте». Вони будуть завантажуватися за допомогою автоматично оновлюється на сервері скрипта, таким чином, в адмінці будуть актуальні записи зі сторінки адміністратора і груп, в яких він складається.

Поля моделі:

class Vk_posts(models.Model):
group = models.CharField(max_length=1000, verbose_name=u ' Сторінка/група', blank=True)
text = HTMLField(verbose_name=u ' Текст запису', blank=True)
date = models.DateTimeField(verbose_name=u ' Дата публікації', blank=True)


Для моделі статті я переопределила метод save(), щоб при збереженні якої-небудь статті відбувалося звернення до API Вконтакте і проводилася відправка записи у «Вконтакте», якщо поставлені відповідні галочки.

def save(self, *args, **kwargs):
use_vk(self) 
model = super(Page, self).save(*args, **kwargs)


Перед збереженням викликається функція use_vk, в якій відбувається звернення до API.

#шляху для фото і документів
photo_vk_path = 'photo_vk'
files_vk_path = 'files_vk'

def use_vk(self):
#складання запису
msg = self.title + '\n' + self.text
msg = re.sub('<.*?>',",msg)
#прапор для визначення, чи потрібно відправляти запис
post_vk = 0
#отримання списку груп 
groups = [g for g in self.group_vk.all()]

if len(groups) or self.wall_user_vk:
post_vk = 1

if post_vk:
attachments = []
#для прикріплення фото
if self.photo_vk:
server = vk.photos.getWallUploadServer(uid = my_id)
path = MEDIA_ROOT + photo_vk_path + '/' + re.split('/', self.photo_vk.url)[-1]
r = requests.post(server['upload_url'], files={'photo': open(path,"rb")})
params = {'server': r.json()['server'], 'photo': r.json()['photo'], 'hash': r.json()['hash']}
wallphoto = vk.photos.saveWallPhoto(**params)
attachments.append(wallphoto[0]['id'])
#для прикріплення документа 
if self.file_vk:
server = vk.docs.getWallUploadServer()
path = MEDIA_ROOT + files_vk_path + '/' + re.split('/', self.file_vk.url)[-1]
r = requests.post(server['upload_url'], files={'file': open(path,"rb")})
params = {'file': r.json()['file']}
doc = vk.docs.save(**params)
attachments.append('doc' + str(my_id) + '_' + str(doc[0]['did']))

params = {'attachments': ','.join(attachments), 'message': msg}
#для відправки запису на стіну адміністратора
if self.wall_user_vk:
params['owner_id'] = my_id
vk.wall.post(**params)
#для відправки запису у вибрані групи 
if len(groups):
if self.group_stat:
params['from_group'] = 1
for g in groups:
params['owner_id'] = g.gid
vk.wall.post(**params)


Потрібно відзначити, що завантажувач для фото і документів видавав некоректний шлях до файлів у папках за викликом методу url (не виключаю, що це саме у мене), тому я сама складала шлях до зображень і документів (змінна path).

Детальніше про етапи завантаження фото або документа до запису:

a) Відправка запиту на отримання адреси сервера Вконтакте, куди можна завантажити фото або документ;
b) Отримання адреси сервера Вконтакте;
c) Формування post-запиту за адресою сервера з завантаженням на нього документа або фото;
d) При успішній завантаженні отримання відповіді з ідентифікатором завантаженого документа або фото;
e) Формування списку атрибутів для розміщення запису у Вконтакте, в числі яких ідентифікатор фото або документа.

Після прикріплення фото/документа використовується завершальний метод API vk.wall.post(**params), що відправляє запис на стіну адміністратора/групи запис.

Для отримання списку груп і збереження нових записів з груп і зі стіни адміністратора використовується скрипт, який автоматично оновлюється на сервері в заданий час. Даний скрипт отримує налаштування django, імпортує до себе необхідні моделі і файл отримання сертифіката, а потім через API отримує групи адміністратора, записи зі стіни/з груп і оновлює таблиці бази даних:

import sys
import time
sys.path = ['C:/site/umc/'] + sys.path
from django.core.management import setup_environ
import settings
setup_environ(settings)

from www.models import Vk_groups, Vk_posts
from umc.vk_response import *

count_posts = 15

def get_posts(owner_id, g_name):
"""Функція отримання записів зі стіни адміністратора і груп і додавання нових записів в таблицю Vk_posts"""
params = {'owner_id': owner_id, 'count': count_posts}
answer = vk.wall.get(**params)
for i in range(count_posts):
params = {
'group': g_name,
'text': answer[i+1]['text'],
'date': time.strftime("%Y-%m-%d %H:%M:%S+06:00", time.localtime(answer[i+1]['date']))
}
try:
Vk_posts.objects.get_or_create(**params)
except:
params['text'] = u ' Неможливо відобразити текст статті'
Vk_posts.objects.get_or_create(**params)


#додавання нових груп у таблицю Vk_groups
params = {'owner_id': my_id, 'extended': 1, 'filter': 'events, groups, admin'}
answer = vk.groups.get(**params)
for i in range(answer[0]):
Vk_groups.objects.get_or_create(title = answer[i+1]['name'], gid = '-' + str(answer[i+1]['gid']), is_admin = answer[i+1]['is_admin'], is_closed = answer[i+1]['is_closed'])

#додавання нових записів з груп в таблицю Vk_posts
groups = Vk_groups.objects.all()
for g in groups:
get_posts(g.gid, g.title)

#додавання нових записів зі стіни користувача в таблицю Vk_posts 
user = vk.users.get(uid = my_id)
get_posts(my_id, user[0]['first_name']+ ' ' + user[0]['last_name'])


Власне, тепер можна спробувати відправити записи з адмінки на стіну або будь-яку групу (якщо права доступу дозволяють розміщувати записи на стіні групи) і перевірити роботу.

Сподіваюся, стаття була корисною.

Всім приємної роботи з Django!

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.