Django: Ajax comment deletion

No matter how much anti-spam measures you implement, sooner or later some comments that you don't like will end up on your site. You can use a moderated-only policy, but if you don't it makes sense to use some javascript code to allow easy deletion of your comments from within the page. Anyway, here is my solution, quite simple, but now I can delete unwanted comments with one click directly on the page. This example assumes, that the backend is build with Django and django.contrib.comments.

First, I assume your comments are displayed somewhat like this (removed unnecessary markup):

{% get_free_comment_list for myapp.article object.id as comment_list %}
<ul>
{% for comment in comment_list %}
    <li class="comment {% cycle row1,row2 %}">
    {{ comment.comment|escape|linebreaksbr }}<br />
    {{ comment.person_name|escape}},
    {{ comment.submit_date|date:"Y-m-d" }}
    </li>
{% endfor %}
</ul>

Now two things are added: Every list-element gets an id in the form of "c" + "comment.id" and at the end of the comment, after name and postdate, a link is added with an onlick handler which calls a javascript function. The code should now look like this:

{% get_free_comment_list for myapp.article object.id as comment_list %}
<ul>
{% for comment in comment_list %}
    <li id="c{{comment.id}}" class="comment {% cycle row1,row2 %}">
    {{ comment.comment|escape|linebreaksbr }}<br />
    {{ comment.person_name|escape}},
    {{ comment.submit_date|date:"Y-m-d" }}
    {% if perms.comment.can_delete %}
        <a onclick="javascript:cdel.delete_comment({{comment.id}});
        return false;"
        href="#c{{comment.id}}">[x]</a>
    {% endif %}
    </li>
{% endfor %}
</ul>

The condition {% if perms.comment.can_delete %} only shows the delete-link to users, who are logged in and have the permission to delete comments.

The last step is to implement the delete_comment javascript function. Instead of adding it in an extra .js file and including it, I just used the same condition as above and added the code directly to a template block extrahead, which injects the code into the <head> of the page (You need to define ` the block in your base-template yourself). The code uses the YUI library, because I already use it for other things on the page. Implementing it with other javascript toolkits should be straight forward. The code looks like this:

{% block extrahead %}
{% if perms.comment.can_delete %}
<script type="text/javascript" charset="utf-8">
var cdel = {
    delete_comment: function(cid) {
        cdel.cid = cid;
        var resp = YAHOO.util.Connect.asyncRequest(
            "POST", "/admin/comments/freecomment/"+cid+"/delete/",
            cdel.ajaxCallback, 'post=yes'
        );
    },
    ajaxCallback: {
        success: function(o) {
            el = document.getElementById('c'+cdel.cid)
            el.parentNode.removeChild(el);
        },
        failure: function(o) {
            alert('error'+o);
        }
    }
}
</script>
{% endif %}
{% endblock %}

If the delete-link on a comment is clicked it calls the delete_comment function with the id of the comment, which should be deleted. The javascript makes an XMLHTTP POST request to the builtin admin view from django for deleting comments (in this case freecomments). If you use django.contrib.comments and django.contrib.admin in your INSTALLED_APPS you automatically get this view.

If the XMLHTTP-Request was succesfull the list-element (and therefore the comment) is instantly removed from the page, otherwise an alert pops up. Error-handling could of course be improved, but as only I and a few trained moderators will use this solution it will suffice.

That's all. Now you can delete comments with one click on the [x]-Link, which is displayed beside every comment. You don't have to write a single line of python code, just modify your template. Permissions are automatically handled by Django (not only in the template, but also in the backend, where the deletion actually happens), so nobody without the comment.can_delete permisson will be able to delete a comment. One caveat: Users with comment.can_delete permisson but without staff-status may be unable to delete comments with this technique, because we use a view from the admin-interface to actually delete the comment and only users with staff-status can access the admin-interface.


Kommentare