http://habrahabr.ru/post/236875/
Доброго времени суток, Хабр!
Недавно разрабатывала сайт на 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!