django-hitcount: simple app to count hits/views for an object
django-hitcount: a simply django application that allows you to count hits/views on a per object basis. This app came about as an answer to my own question at stackoverflow.com. Am hoping that others will find it useful.
This isn’t meant to be a full-fledged tracking application (see django-tracking) or a real analytic tool (try Google Analytics); rather, it’s meant to simply count the number of hits/view on an object-per-object basis.
How to install:
I find that the easiest way to work with django apps is to symbolically link them to my site-packages directory. It’s easier to update the apps with svn, git, or hg than it is to manually download the files and install by hand.
For me, this is what it looks like (you can cut and paste to make it easy):
cd ~/srcgit clone git://github.com/thornomad/django-hitcount.gitsudo ln -s `pwd`/django-hitcount/hitcount `python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"`/hitcount
Test it works by loading python and checking the version (should not get an error):
>>> import hitcount >>> hitcount.__version__ '0.1 alpha' >>>
Adding to your django project:
Add the hitcount app to your INSTALLED_APPS tuple and run syncdb.
There are two additional settings you can add to your settings.py file:
HITCOUNT_KEEP_HIT_ACTIVE = { 'days': 7 }
HITCOUNT_HITS_PER_IP_LIMIT = 0
HITCOUNT_EXCLUDE_USER_GROUP = ( 'Editor', )
HITCOUNT_KEEP_HIT_ACTIVE: is the number of days, weeks, months, hours, etc (timedelta kwargs), that an Hit is kept ‘active’. If a Hit is ‘active’ a repeat viewing will not be counted. After the active period ends, however, a new Hit will be recorded. You can decide how long you want this period to last …
HITCOUNT_HITS_PER_IP_LIMIT: limit the number of ‘active’ hits from a single IP address. 0 means that it is unlimited. You may want to set this, or not.
HITCOUNT_EXCLUDE_USER_GROUP: don’t count any hits from certain logged in users. In the example above, I don’t want any of my editors inflating the total Hit count.
Adding to your urls.py:
You need to add one line to your urls.py file.
You can have this url, itself, point to anywhere you like, but you need to keep the name='hitcount_update_ajax' constant.
from django.conf.urls.defaults import *
from django.views.generic.list_detail import object_detail
from hitcount.views import update_hit_count_ajax
urlpatterns = patterns('',
url(r'^ajax/hit/$', # you can change this url if you would like
update_hit_count_ajax,
name='hitcount_update_ajax'), # keep this name the same
# other views, for example my object view is:
url(r'^/video/(?P<object_id>\d+)$', object_detail,
{ 'queryset': Video.objects.all(),
'template_name': "video/view.html"},
name='video_detail_view'),
)
Edit your templates
Add the javascript to your object_detail templates (or any template that handles a single object) so that our hit counter is called after the document loads.
Here is what my head includes:
{% load hitcount_tags %}
<script src="/media/js/jquery-latest.js" type="text/javascript"></script>
<script type="text/javascript"><!--
$(document).ready(function() {
{% get_hit_count_javascript for object %}
});
--></script>
When the template is rendered, it should turn into something like this:
$(document).ready(function() {
$.post( '/ajax/hit/',
{ hitcount_pk : '3' },
function(data, status) {
if (data.status == 'error') {
// do something for error?
}
},
'json');
});
Display the hits!
The most exciting part, is actually displaying your hits. There are four different ways to do it:
- Return total hits for an object:
{% get_hit_count for [object] %}
- Get total hits for an object as a specified variable:
{% get_hit_count for [object] as [var] %}
- Get total hits for an object over a certain time period:
{% get_hit_count for [object] within ["days=1,minutes=30"] %}
- Get total hits for an object over a certain time period as a variable:
{% get_hit_count for [object] within ["days=1,minutes=30"] as [var] %}

Why do you include the ajax call? Wouldn’t it be much simpler to just update your db via the template tag? It seems that including a POST request is unnecessary.
You could do that – however, the AJAX approach is just one way to try and counter ‘false counts’ … if it was triggered by a database hit (or page load) all the web crawlers and bots would set off hits every time the page read … which would be a lot. AJAX, hopefully, helps to ensure that only real computer users are triggering a hit.
Hmmm I guess that makes sense…although for bots one step could be to check the user-agent string. It wouldn’t prevent people purposefully spamming, but then neither would the ajax method.
As far as bot checking goes, it looks like you could either run the UA past all of the known bot UA strings (http://www.pgts.com.au/pgtsj/pgtsj0208d.html) or just check for the major browsers.
That’s a great idea!
I would love to implement some alternative methods to recording a Hit … if you look under the
views.pyyou’ll see I separated the base Hit processing method [_update_hit_count(request, hitcount)] from the ajax method.If you wanted to fork the project and add another view method that utilizes the UA list and doesn’t require javascript, I would be happy to test it and merge it into the master branch. I think it would be useful for people who aren’t already using jQuery.
If you aren’t up for it, I will try and add that feature when I have a chance … contact via github if you are interested.
Thanks for the idea!
I opened a ticket:
http://github.com/thornomad/django-hitcount/issues/#issue/3
Comment there with input. Shouldn’t be that hard to implement … importing the list of UA’s will be the major work … if it can be called that.
I haven’t tried this out yet, I’m planning on implementing it tonight. It’s exactly what I was looking for. I hope it works out wells. Cheers.
Let me know how it works – it isn’t as full-featured as I would like, yet, but seems to get the job done so far. If you have any contributions to make would love to incorporate them.
Hi Damon. So far so good. I’m actually fairly new to Django and had a question. I’m making a video site and am using this to keep track of video views. Lets say I wanted to display the last 2 videos that recorded a view, could I do that using your app? I’m having trouble figuring it out (this is the first website I’m actually programming, so I don’t know too much..). If you have some sort of answer to that, feel free to email me as well. Thank you!
Well, every time a Hit is saved the associated HitCount objects
modifiedvalue is updated. So, you could get the last two like so:>>> from hitcount.models import HitCount >>> for hc in HitCount.objects.order_by('-modified')[:2]: ... hc.content_object ... <Video: Stars & Stripes FOREVER! [HD]> <Video: The Muppets Bohemian Rhapsody> >>>That should get you started …
Amazing, man. Works out of the box!
Thanks a lot!!
Nice, thanks for this. You forgot to add the following command templates:
{% load hitcount_tags %}Thanks for pointing that out and hope you find it useful.