Andrew C
Andrew C

Reputation:

Increment Page Hit Count in Django

I have a table with an IntegerField (hit_count), and when a page is visited (for example, http://site/page/3) I want record ID 3's hit_count column in the database to increment by 1.

The query should be like:

update table set hit_count = hit_count + 1 where id = 3

Can I do this with the standard Django Model conventions? Or should I just write the query by hand?

Upvotes: 17

Views: 9497

Answers (4)

Carl Meyer
Carl Meyer

Reputation: 126581

If you use Django 1.1+, just use F expressions:

from django.db.models import F
...
MyModel.objects.filter(id=...).update(hit_count=F('hit_count')+1)

This will perform a single atomic database query.

As gerdemb says, you should consider putting this in a middleware to make it easily reusable so it doesn't clutter up all your views.


Upvotes: 33

Javier
Javier

Reputation: 62593

As gerdemb says, you should write it into a middleware to make it really reusable. Or (simpler) write a function decorator. In fact, there are adaptors to use a middleware as a decorator and viceversa.

But if you're worried about performance and want to keep the DB queries per page hit low, you can use memcached's atomic increment operation. of course, in this case, you have to take care of persistence yourself.

Upvotes: 4

gerdemb
gerdemb

Reputation: 11477

I would start by looking at the documentation for middleware. Ignacio's comment about the lack of atomic transactions is true, but this is a problem with the entire Django framework. Unless you're concerned about having a 100% accurate counter I wouldn't worry about it.

Upvotes: 0

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798666

The model conventions won't be atomic; write it by hand:

BEGIN
SELECT * FROM table WHERE id=3 FOR UPDATE
UPDATE table SET hit_count=hit_count+1 WHERE id=3
COMMIT

Upvotes: 0

Related Questions