Comments have been closed for this post.
Hello, my name is Federico Capoano,
I enjoy developing cutting-edge websites
and working with creative people.
25th October 2010 in Coding Tags: django, performance, programming, staticgenerator
If like me you are using Django StaticGenerator to speed up your blog you should have noticed that your comments won't work anymore, since StaticGenerator will cache also the fields used by the django comment app to block spam and CSRF attacks.
In this post I'll share with you a quick and easy solution using jQuery.
When I launched this blog I decided to disable the caching of the single posts because I didn't have enough time to look for a solution that would make it work with StaticGenerator.
I soon found my server crashing badly when I got loads of traffic coming from stumbleupon... and that was really bad: infact all the stumblers would rate my site down because it wasn't working properly. So instead of getting loads of thumbs up, reviews and traffic I instead got my server down, all my sites not working, some clients annoyed and some thumbs down for my articles.
I had to find a solution for that!
This might not be the best solution, but it took me about 15 minutes to get it working and it solved the problem: my server didn't crash anymore, and that's what is important!
How does this work? Simple: let's create an ajax view that retrieves the post and then pass it to a template that just prints the comment form. Then we'll add some jQuery code to retrieve the comment form asynchronously.
# views.py from blog.models import Post from django.shortcuts import get_object_or_404 from django.template import RequestContext def ajax_comment_form(request, id): """ Display comment form for requried post """ post = get_object_or_404(Post, pk=id) context = { 'post': post } return render_to_response('blog/ajax_comment_form.html', context, context_instance=RequestContext(request))
Change "get_object_or_404(Post)" with the correct model name you are using in your project and "blog/ajax_comment_form.html" with the right path to the template we'll create in a moment.
# urls.py urlpatterns = patterns('', url(r'^commentform/(?P<idgt;\d+)/$', view='blog.views.ajax_comment_form', name='ajax_comment_form' ) )
Change 'blog.views.ajax_comment_form' with the right path to the view.
Create the template "ajax_comment_form.html" in the right path according to what you've set in the file view.py. This file will contain just two django template tags:
{% load comments %} {% render_comment_form for post %}
Open the template for you post detail page and simply add a wrapper div tag for your comment form named "form2replace":
<div id="commentformcontainer"> {% if object.allow_comments %} <h3>Leave your comment</h3> <div id="commentform"> <!-- add <div id="form2replace"> --> <div id="form2replace"> {% render_comment_form for object %} </div> </div> {% else %} <h3 class="functional"><span>Comments are closed.</span></h3> <div id="commentform"> <p>Comments have been closed for this post.</p> </div> {% endif %} </div>
Assuming that you're already loading jQuery in your website, this is the code I used:
<script type="text/javascript"> //<![CDATA[ $(function() { f = $("#form2replace"); if(f.length > 0){ $.ajax({ type: "POST", url: "{% url ajax_comment_form object.id %}", dataType: "html", success: function(response) { f.html(response); } }); } } //]]> </script>
Just change object.id with the name of the right variable name containing the id of your post.
Since this Javascript will be the same for all the articles in your blog, it wouldn't be a bad idea to save it in an external javascript file so it would be cached by the browser.
But hey, wait a moment! There's {% url %} tag here.. how to put that in an external js file?
First of all create the file "ajax_comment_form.js" that will contain the jQuery code with a slight tweak:
// ajax_comment_form.js $(function() { f = $("#form2replace"); if( f.length > 0){ $.ajax({ type: "POST", url: __comment_form_url__, dataType: "html", success: function(response) { f.html(response); } }); } }
Then at the end of your template file add the following code:
<script type="text/javascript">var __comment_form_url__ = "{% url ajax_comment_form object.id %}"</script> <script src="{{ MEDIA_URL }}/js/ajax_comment_form.js" type="text/javascript"></script>
Again change object.id and the right path to your js file.
I know this solution is not the perfect one. It would be better to not query the database at all and avoid to use javascript.
Unfortunately the perfect solution needs more time to be implemented and I just didn't have that recently.
But if you did then please share it with me! :-)
“ I got very good results with this, thanks for sharing. ”
By Yasir Atabani in How to speed up tests with Django and PostgreSQL
“ Hi Amad, for any question regarding OpenWISP, use one of the support channels: http://openwisp.org/support.html ”
By Federico Capoano in How to install OpenWISP
“ Sir please guid , i have install the ansible-openwisp2 , now how to add the access points . What is the next procedure . Please help. ”
By Ahmad in How to install OpenWISP
“ Hi Ronak, for any question regarding OpenWISP, use one of the support channels: http://openwisp.org/support.html ”
By Federico Capoano in netjsonconfig: convert NetJSON to OpenWRT UCI
“ Hi, I have installed openwisp controller using ansible playbook. Now, i am adding the configurations automatically using OPENWRT devices in openwisp file by specifying shared_key so can you suggest me if I want to set limit to add configuration how can i do it? ”
By Ronak in netjsonconfig: convert NetJSON to OpenWRT UCI
JagoanLeks said:
( on 3rd of November 2010 at 22:30 )
“sorry I'm still a beginner in this hall.
Can you teach me?
Usually I just download the complete template / layout.
T__T”
me said:
( on 2nd of March 2011 at 19:13 )
“Just a test!
greetings”
Béres Botond said:
( on 18th of March 2011 at 12:06 )
“I believe this is a nice compromise between speed and functionality. Staticgenerator is lightning fast since well it's just about serving static html, however that's going to be a problem with any dynamic page sections.
For best performance I think the next step would be to cache the comments also separately with something like memcache. (or even better...staticgenerator :P)”
Federico Capoano said:
( on 14th of September 2011 at 11:13 )
“@Bères Botond:
There would be no point of caching the comment form with static generator, otherwise why would I have ever done this hack in the first place?
The comment form cannot be cached because it contains the django csfr token that changes for every user.
Another solution would be to try generating the csfr token dynamically with javascript or to eliminate it completely, but i'm not sure these solutions are much better than the one proposed here.”
Federico Capoano said:
( on 24th of October 2011 at 12:31 )
“Now that I have more experience with django I don't get why I just didn't disable the csrf protection for the comment form! :-D”
halcion said:
( on 5th of February 2012 at 14:34 )
“Staticgenerator is lightning fast since well it's just about serving static html, however that's going to be a problem with any dynamic page sections. Thanks .”