📜 ⬆️ ⬇️

Django + API Vkontakte: post entries with attachments, get a list of groups and entries

image


Good day, Habr!

Recently I developed a python / django site and I needed the ability to use the Vkontakte API. Namely:
')
• Posting articles from site to page in Vkontakte, as well as to selected groups (in which the administrator was a member);
• The ability to attach documents and pictures to the records;
• Getting a list of groups and records using the updated script and uploading all this to the django admin area.

Actually, for the administrator, this functionality is managed through the admin area.

I'll tell you step by step the implementation of this functionality.

At the first stage, the administrator needs to create his application in "Vkontakte", and also get a token to work with the API. To get a token, I use the VKAppAuth module ( link to GitHub, there is also an example of using the module).

Settings for getting saved in a separate file and connect it to models.py. In models.py I add fields for "Vkontakte" to the article model:

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) 


The group_vk field displays all Vkontakte groups from the Vk_groups table. The code for the Vk_groups class in 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 = " " 


Also created a model for records "Vkontakte". They will be loaded using a script automatically updated on the server, so the admin panel will have actual entries from the admin page and from the groups in which it belongs.

Model Fields:

 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) 


For the article model, I redefined the save () method so that when you save any article, you access the Vkontakte API and send the record to Vkontakte, if the corresponding checkboxes are set.

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


Before saving, the use_vk function is called, in which the API is accessed.

 #     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) 


It should be noted that the bootloader for photos and documents produced an incorrect path to files in folders by calling its url method (I do not rule out that it was me), so I myself composed the path to pictures and documents (path variable).

More information about the stages of uploading a photo or document to an entry:

a) Sending a request for the address of the server Vkontakte, where you can upload a photo or document;
b) Getting the address of the server Vkontakte;
c) Formation of a post-request to the server address with the loading of a document or photo on it;
d) Upon successful upload, receiving a response with the identifier of the uploaded document or photo;
e) Formation of a list of attributes for posting to Vkontakte, including the ID of a photo or document.

After attaching a photo / document, the final API vk.wall.post (** params) method is used, which sends an entry to the administrator / group wall entry.

To get a list of groups and save new records from groups and from the administrator's wall, a script is used that is automatically updated on the server at a specified time. This script receives the django settings, imports the necessary models and the token receipt file to itself, and then, through the API, receives the administrator groups, records from the wall / from the groups, and updates the database tables:

 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']) 


Actually, now you can try to send records from the admin to the wall or any group (if the access rights allow you to place the records on the group wall), and check the work.

Hope the article was helpful.
Link to the project: github.com/julia-bikova/DjangoVkPosting

Enjoy your work with Django!

Source: https://habr.com/ru/post/236875/


All Articles