tags:

views:

472

answers:

3

I am sure that someone has a pluggable app (or tutorial) out there that approximates this, but I have having trouble finding it: I want to be able to track the number of "views" a particular object has (just like a question here on stackoverflow has a "view count").

If the user isn't logged in, I wouldn't mind attempting to place a cookie (or log an IP) so they can't inadvertently run up the view count by refreshing the page; and if a user is logged in, only allow them one "view" across sessions/browsers/IP addresses. I don't think I need it any fancier than that.

I figure the best way to do this is with Middleware that is decoupled from the various models I want to track and using an F expression (of sorts) -- other questions on stackoverlow have alluded to this (1) (2) (3).

But I wonder if this code exists out in the wild already -- because I am not the savviest coder and I'm sure someone could do it better. Smile.

Have you seen it?

+2  A: 

I repost my idea, that I already wrote as an answer to one of the mentioned questions, where it didnt raised any attention :D

you could create a generic Hit model

class Hit(models.Model):
    date = models.DateTimeFiles(auto_now=True)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

in your view.py you write this function:

def render_to_response_hit_count(request,template_path,keys,response):
    for  key in keys:
        for i in response[key]:
             Hit(content_object=i).save()
    return render_to_response(template_path, response)

and the views that you are interested in return

return render_to_response_hit_count(request,   'map/list.html',['list',],
        {
            'list': l,
        })

This approach gives you the power, not only to count the hit, but to filter the hit-history by time, contenttype and so on...

As the hit-table might be growing fast, you should think about a deletion strategy.

Code untested

vikingosegundo
Yea - I did see your code, and it did raise my attention! Smile. However, was hoping for something already in an app that I could just import and then use ... but, I may try and combine your Hit model (and the generic aspects) with the session suggestions of @Teebes. Thanks.
thornomad
Sure, u should combine them. with session u get the informations about single users. and with my approach u can control the views to be triggered without writing the same code over and over again. take that to ur solution.
vikingosegundo
+2  A: 

You should use the django built-in session framework, it already does a lot of this for you. I implemented this in the following way with a Q&A app where I wanted to track views:

in models.py:

class QuestionView(models.Model):
    question = models.ForeignKey(Question, related_name='questionviews')
    ip = models.CharField(max_length=40)
    session = models.CharField(max_length=40)
    created = models.DateTimeField(default=datetime.datetime.now())

in views.py:

def record_view(request, question_id):

    question = get_object_or_404(Question, pk=question_id)

    if not QuestionView.objects.filter(
                    question=question,
                    session=request.session.session_key):
        view = QuestionView(question=question,
                            ip=request.META['REMOTE_ADDR'],
                            created=datetime.datetime.now(),
                            session=request.session.session_key)
        view.save()

    return HttpResponse(u"%s" % QuestionView.objects.filter(question=question).count())

Vikingosegundo is probably right though that using content-type is probably the more reusable solution but definitely don't reinvent the wheel in terms of tracking sessions, Django already does that!

Last thing, you should probably have the view that records the hit be either called via Ajax or a css link so that search engines don't rev up your counts.

Hope that helps!

Teebes
That does help - how you used the session information and everything is going to be useful. I like vikingosegundo's approach too - which is more generic. If I can't find anything else, I may combine the two. And, will have to keep in mind search engines - I hadn't thought of that. But they may include a certain header, that could be checked ... no?
thornomad
You can definitely check the headers. this previous question http://stackoverflow.com/questions/45824/counting-number-of-views-for-a-page-ignoring-search-engines has some very good info on this (non django specific).
Teebes
+3  A: 

I am not sure if it's in the best taste to answer my own question but, after a bit of work, I put together an app that solves the problems in earnest: django-hitcount.

You can read about how to use it (rough guide, for now) at my website.

The ideas for django-hitcount came came from both of my two original answers (Teebes -and- vikingosegundo), which really got me started thinking about the whole thing.

This is my first attempt at sharing a pluggable app with the community and hope someone else finds it useful. Thanks!

thornomad
Nice, I will check it out!
vikingosegundo