Django’s bundled comments application (found in django.contrib.comments) is incredibly useful; it gives you a nice, out-of-the-box system for adding comments to any site. But, if you look at it closely, really feels more like two applications:
Comment model and its helpers, which only allows registered user accounts to post comments.
FreeComment model and its helpers, which allows anyone at all to post comments.
The first one — based around Comment — is much more complex by far, and includes pretty much everything World Online has ever needed for its various news and community sites: reviews, ratings, attached images, reputation over time, flagging of potentially bad content, user bans and groups of moderators who can remove comments. Explaining everything it can do would take several extremely long articles.
The second one — based around FreeComment — is extremely simple, and doesn’t have all the fancy bells and whistles of its big brother; its model is a heavily distilled set of fields, and it mostly just lives to attach basic comment objects to any bit of content you throw at it. There are plenty of use cases where this is ideal, since lots of sites don’t need or want all of the features and administrative overhead that come with the Comment model and the simplicity makes FreeComment pretty easy to understand; a simple one-page tutorial suffices to explain most of the things you’ll need to know to use it.
But then there are cases which fall somewhere in between: for example, if you want to allow anyone to comment without needing an account, but want a little more flexibility in controlling and filtering the comments that get posted and displayed.
Some of that flexibility is baked in, if you know how to use it, but some of it isn’t; in this article I’ll be walking through some tricks you can do with comments, and some modifications you can make to the FreeComment-based system to get some useful extra functionality.
Warning! Some of what I cover here is going to require you to make changes to the code in your copy of Django, which may cause hassles when upgrading or restrict your interoperability with any code that assumes a pristine copy of django.contrib.comments. Think things through and weigh your options carefully before you try any of this on a production application.
Edit one year later: I’d like to re-emphasize the above, and even go a little further. Don’t do what this entry describes. I did, way back before I wrote this up, and I’m now clawing my way back out of it one line of code at a time. I’ve posted an unobtrusive comment-moderation function on djangosnippets, and I’ve got a few other things in the works to replicate the things this entry does, but in ways that don’t touch Django’s code at all. So, again, don’t do any of the things listed below; they’ll just cause you pain.
Edited again: no, really, don’t use this. Check out this generic application which provides comment moderation without having to hack on Django. In light of that, I’ve removed the remainder of this entry.
Comments for this entry are closed. If you'd like to share your thoughts on this entry with me, please contact me directly.
Awesome, James. I know there are a lot of people who’ve been wanting to know this stuff. Just a few random comments (no pun intended):
Lots of people (including at least one of the Django lead developers) have talked about refactoring FreeComment to be more flexible. The idea I’ve heard bandied about is to let any model be the freecomment model, via something similar to AUTH_USER_PROFILE_MODULE. As long as the model had a generic ForeignKey, it could be your FreeComment model, which means it would be simple to name your own fields for comments. People often ask how to add e-mail address and URL fields to FreeComment — and there really isn’t a great way now that doesn’t involve hacking up the comments module. This would solve that. I mention it here in hopes someone will take up the challenge and submit a patch. :)
Akismet freaking rocks. One my site, it’s catching in excess of 45 comment spam messages per day. Since I configured it (a couple months ago), it’s caught flagged only one message as spam that wasn’t. That’s a pretty damn good success rate.
People should totally check out the registered-user Comment module. I understand that it’s typical to not require registration for comments on a weblog, and that’s fine. But, take a look at it anyway — the flexibility there is insane. I used it on LOST-theories.com to let people rate every item they comment on a part of the comment submission process. Like you said, it included the ability to attach images, has a “karma” feature, and more. It’s really thorough. Hell, you could probably build a PunBB-style forums app using only the built-in Comment functionality.
Great post, James.
James…just thought of a question for you related to this. As you know, one common tact some people have taken is to make a copy of the built-in comments app (i.e. move it into your personal projects area, rather than using the copy in django.contrib.comments) and hack on it, instead of the django.contrib.comments version.
What’s your feeling on this? Better to make a copy and go to town on it, or modify the existing django.contrib.comments?
James.. an excellent writeup.
one small nit, askimet isn’t free for everyone.
Thanks for another great write-up, James. This is going to help me a ton.
I’m sure you know this already, but it looks like you need to update your template tag for the latest comments to check if they are public or not. I’m using your template tags, and just put that check in the template, which I’m sure isn’t the best place for it, but I didn’t know where else I could put it, since the field for publishing status is different for my different models (I guess I could change that to be standard, but I wasn’t familiar with the comments app when I made my entry model).
Tony,
Yeah, I was shuffling a lot of stuff around as I wrote this, particularly Akismet. There was a period where a bunch of comment spam showed up in the recent comments list even though it wouldn’t show up anywhere else, but that’s fixed now.
Jeff,
I’m pretty sure that before I release the code behind my blog, I’ll break out comments into a new application, since I’ve done quite a bit of hacking on them to add fields, add all the moderation/Akismet stuff, etc.
I think that a useful metric there is just how much hacking you do; if you’re just adding one or two small changes that aren’t likely to be overwritten in trunk (like tacking a custom
savemethod on the comment model), it’s probably less hassle to just do it directly indjango.contrib.comments, but if you’re making lots of changes all over the app, it’s going to be better to split it out into a new application and use that.Another useful metric is whether or not you’re only using the
django.contrib.commentsfor one project, or if you’re using it in several different projects.If you’re using it in more than one project, then customizing the default comments would force all of the projects to use the same comments system, but if one project needs the extended flexibility, then it makes more sense to break it out into its own application.
great post i can’t wait for .95 to come out and to get better documentation
There’s a small typo in your
comment_period_openfunction. An underscore is missing inself.enable_comments