Despite the fact that this social sphere is “dearly loved” by the audience of Habr, I still decided to take a chance and publish small notes devoted to the development of applications on Dzhanga for it.
I warn you, some of them are quite captain, and some have nothing to do with Vkontakte or even Jange, in general, do not blame me.
Under the cut:
- django-vkontakte-iframe and vkontakte
- Download the application on the wall
- Flash Stub
- Session in beloved IE
- All “flashVars” are sent by the GET request.
- Work in the frame
- Access to user information
- Checking the validity of the layout
- JSLint is your friend and comrade
- Thumbnail generation
- Moderation through a proxy model
- Import Settings
- Optimization
For advertising: The application is called
"Collector" and is intended for people involved in collecting coins, stamps, cards and other items. At the moment, only a catalog of MTG maps is filled, but in the future, catalogs for other items will be created and filled. Of course, we are happy to hear all your suggestions and constructive criticism.
django-vkontakte-iframe and vkontakte
These modules allow you to immediately begin to develop useful functionality without understanding the documentation of the VKontakte API.
')
The first takes on the authorization of users, allowing you to work through the usual dzhangovskih users, but he already
mentioned in Habré by the author himself.
However, after some time, the application began to refuse to identify users. The problem was in the refferer field, in vk_iframe / forms.py it is spelled as follows:
referrer = forms.ChoiceField (REFERRER_CHOICES, required = False)From the
documentation it can be concluded that the REFERRER_CHOICES specified in the module are outdated, and besides, the fixed list does not suit us because of ad_ {AD_ID}. Therefore, a logical replacement will solve our problems:
referrer = forms.CharField (required = False)Of course, REFERRER_CHOICES is no longer needed and can be safely removed.
The second module presents a wrapper for the API, but firstly not all methods can be used from the server, and secondly, in my opinion, in most cases it is more convenient and optimal to access the API via javascript from the user’s page. In the application under development, I used this module in a small
middleware to periodically update user profiles created by django-vkontakte-iframe and to get the user's friends to determine if the caller has the right to view the pages owned by the user for which “Show only me and friends” is displayed.
It is worth noting a funny moment, on June 16, when trying to access the page, the application suddenly began to show ... nothing. Viewing requests showed that the 500th error is returned to a single request. Those. Please note that this was returned not by the application, but by Vkontakte itself! A short investigation showed that the case was in the first request to the API, but after a while the situation returned to normal.
Download the application on the wall
For the promotion of an application, it is often useful to add the ability for the user to place on the walls of friends a message generated by the application, at the click on which people will enter the application. In our case, this was a “boast” subject in the user's collection.
The sequence of publication is simple:
- Get the user id on the wall which will be posting
- You get the server address for uploading photos using wall.getPhotoUploadServer
- You form a request with the photo field containing the desired photo to the specified POST address
- Call wall.savePost with the received photo data and specify the message with the recipient
- And show the user a confirmation window using the JS API saveWallPost method
Most of all I had to torment myself with uploading a photo, primarily because of my own inattention. The
documentation had to follow the instructions “Downloading an application to the user's wall”, and I persistently tried to follow “Uploading photos to the user's wall”.
I advise you to pay attention to the inaccuracy in the instructions, in response to the upload of a POST photo with a request, an object comes with a photo field, not photos. Plus, keep in mind that VKontakte resizes a photo up to 75 pixels, so there is no sense to send a very large picture.
And finally, how to create this very POST request. In theory, this can be done by means of javascript, but I did not suffer and made the sending server. Here again there are options, you can form a request with
handles , or you can use a ready-made
module . Personally, I stopped at the second version.
And yes, do not forget to specify post_id when calling wall.savePost, then you will be able to determine what to display to the user who has logged into the application via a message on the wall.
Who cares,
here is a slightly tweaked version of javascript implementing the described algorithm.
Flash Stub
But of course, could not do without a drop of tar. If the user sends a message using the method described above, and having entered the recipient's wall, clicks on it, then the empty window will open.

This happens because Vkontakte tries to display a flash file to the user and he doesn't care that we actually have an iframe. Do not ask why this is so, most interesting.
Well, that’s why you’ll still have to mess around with a flash (or rather just outsource to acquaintances) by creating a
607x412 stub , at least you need to notify the user that you need to open a message on the wall in a new tab, maximally displaying information about a boasting object focusing on post_id To fill the stub, change the type of your application to Flash in the settings, fill the file and change the type back.
Although perhaps this information is already outdated, but the stub may still be useful at the approval stage of the application, since The default administration displays exactly flash, which means they just may not see your creation.
Session in beloved IE
The donkey, of course, could not stand out, so you have to do some gestures especially for him.
A problem with
P3P policies , which is why the application cannot set cookies, and this leads to an authorization file. Fortunately, this is corrected by simply adding the P3P field to the response with the following content: CP = "IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"
In the application, I solved the problem with another
middleware .
UPD: In this
article, the issue with iframe cookies is discussed in more detail and provides possible solutions for potential problems in other browsers.
All “flashVars” are sent by the GET request.
When a user logs in to our application, some useful
information is transmitted. So, all this is transmitted in the usual GET request when entering the main one. Accordingly, if you want more interactivity, then do not be lazy to use it.
The most banal, it is to redirect the user who came into the application from someone's wall from the main to the desired page, focusing on request.GET ['post_id'].
Work in the frame
Do not forget that you are not doing a regular site, but working in a frame. This means that you need to take care of resizing the window using
resizeWindow (take the height of the body or your wrapping div), while the maximum window width is 827 pixels (807 with indents and controls), while keeping in mind that with a width greater than 607 pixels VKontakte interface begins to stretch.
In addition, for the user to have the browser buttons “forward” and “backward”, use
setLocation , and
setTitle should be used to change the name of the parent page.
Plus, you may encounter the fact that third-party front-end applications will stop working normally, for example, I had to finish a little lytebox to make it open normally inside the frame.
Access to user information
Try to design the application so that it would be possible to gradually obtain rights from the user, and it is better that the largest possible part of the application be available without installing the application at all.
So, not only will not each user put a window “And allow me to give up all your information, but also the keys to the apartment where the money is not forgotten,” but you will gradually be offered to expand the rights, while preferably explaining why you really need these rights .
getUserSettings and
showSettingsBox will help you with this.
Oh yeah, do not forget to place in a prominent place a button to invite friends, which works with
showInviteBox .
Checking the validity of the layout
I strongly recommend working only with a fully valid layout. It can save you a lot of time, and it will just bring aesthetic satisfaction to the work done, for example, I spent about an hour figuring out why my frame was not properly resized, and the case turned out to be a crazy div.
In order to simplify the verification process, I put a link in the footer and hung the following
javascript on it. It will not only allow you to monitor the validity of the layout, but also allow it to boast. A kind of banner from the W3C, only clearer. Of course, no one has canceled the tools built into browsers (for example, the context menu item of the Opera “Are Web Standards Compliant”), but, in my opinion, the link on which you can click more clearly and more conveniently, not to mention cross-browser compatibility.
<thinking_aloud> But the ability to load your page into the parent page is practically the realization of a hole, i.e. it is possible to load another site from the iframe of the application, which will be similar to VKontakte, and then already on the thumb. </ thinking_aloud>And between times, feel free to use new tags from html5, to apply styles to them in IE there is a fairly simple solution consisting in creating the right tags through javascript, just google html5 fix. Personally, I try to adhere to this paradigm: "Users of outdated and alternatively gifted browsers will see the page, but more primitive."
JSLint is your friend and comrade
When developing an application, you want, you don't want, but you have to write javascript. And given that this is not usually the main focus of Dzhangistov activity, there is a high chance of making mistakes. JSLint not only allows you to immediately catch stupid errors, but also allows you to keep the code in a very neat form. However, on Habré about him already
written in sufficient detail.
Thumbnail generation
Despite the fact that there are quite solid solutions, for example, the well-known
sorl-thumbnail and
aino-convert , in my opinion, they are too heavy.
Therefore, I adopted
django-thumbs . Fortunately, it consists of only one file providing the extension of the standard ImageField. Understand it and finish to the desired state is not difficult. For example, for the application, I added a watermark attachment (although I’m against them, but these were the requirements), saving the original images to a separate folder and re-generating thumbnails in case settings change.
Moderation through a proxy model
I found a rather interesting technique (unfortunately, the link to the blog is no longer possible to find) when I was looking for how to add moderation for tags added by users, considering that
mptt-admin was already used to display them in the admin panel, so the usual filter was not enough. Its essence is that we create a
proxy model by registering the left application (for example, “Moderating”), and then in admin.py we ask what needs to be displayed (i.e., only non-moderated tags) by defining the queryset method (which is why is
missing in the documentation). Optionally, you can also add a
method for moderating tags in batches.
The result is approximately
as follows . On the use of proxy models, though for several other purposes, you can read
here .
Import Settings
At first, I constantly used this import of settings, as most beginners think:
from settings import foo
But import it like this:
from django.conf import settings
Why exactly, it is better to read in the
documentation .
Optimization
Yes, yes, “Premature optimization is the root of all misfortunes,” but firstly this phrase, according to the author (or not the author, is not important) is true only in 97 percent of cases, and secondly, the measures described below should be taken immediately during development.
Usually the bottleneck of all web applications and, in particular, based on Django are database queries, which is usually aggravated by not very correct use of ORM. However, there is no special sense to spread on the tree, because in the documentation this question is
disclosed in sufficient detail. You can use
django-debug-toolbar or a more wooden
solution to display queries made to the database and their execution time.
But on the other hand, the user is more important than the speed of displaying the page, and not how heavy the server is there, so you need to optimize the load itself. By the way, this is why I wrote above that “it’s best to contact the API via javascript from the user’s page”, since Delay of the response of the VK server can vary greatly, therefore, it is better to do all requests whenever possible after the page has loaded and displayed to the user.
A very useful helper in optimization is
Page Speed . Most often, you first need to minimize everything and everyone.
In the case of html, the question is solved by template tags
{% spaceless%} {% endspaceless%} , while keeping in mind that the tag removes spaces only between tags, so you must either wrap all the text in tags (even between template tags if they go to several lines), or write in such places all in one line, as well as forget, like a bad dream about writing tag attributes in separate lines. In addition, if you used to rely on spacing spaces between tags, you will have to correct and do it entirely in styles. Of course, such a minification is not the height of perfection, but I think that 5-10 per cent, derived from the removal of quotes and other perversions, can be safely neglected. In addition, you should not neglect gzip compression, for which the corresponding
middleware is provided .
Now about css and js. I personally used
django-compress . From the obvious advantages can be called:
- Versioning glued files (which means you will not have to suffer with the cache to display changes)
- Ability to use different compressors (very useful, because the server did not manage to run the CSSTidy binary, so I took YUI Compressor )
- Support for external files, so that the CDN attach is very simple (what a CDN is and why it is actually necessary, you can read it here )
Of course, this module essentially breaks MVC, but I think it is not fatal and very convenient.
Plus worth noting
django-media-bundler . In addition to compressing css and js, it also allows you to automatically create CSS sprites, while immediately minimizing them through
pngcrush , but unfortunately there is no versioning like django-compress. Due to the small number of icons in the application, I decided to leave it for future projects.
In addition, it is very useful to put a semicolon at the end of each js-file, because its absence may result in non-working code after compression.
Well, finally it is worth testing our product for strength.
Load Impact will help us a lot in this. If you're interested, here's
an article telling about it in a little more detail. Of course, free testing is available (up to 50 users), but I recommend not to be stingy and buy at least a basic package (up to 250 users) worth $ 9.
Application tests gave the following results:


It can be seen that the application copes well with the load, but nevertheless, after 70 users, everything depends on the width of the channel provided. So in the end, the movements with the minification of html, css and js, as well as the use of CDN were very useful.
PS: After me, another person worked on the layout, so some of the tips in the application may not be executed.