Cover image for How to track number of hits/views for particular objects in Django | Django Packages Series #2

How to track number of hits/views for particular objects in Django | Django Packages Series #2

coderasha profile image coderasha Updated on ・3 min read

By Reverse Python

What's up DEVs?

Welcome to the second post of Django Packages Series. In this quick tutorial we are going to learn how to track number of views/hits for specific objects.

Tracking is really useful functionality. When user enters your application, number of views can attract user to click specific posts and read it. Also it's good to show users most popular posts.

I saw some solutions on internet related with this topic. Some of developers using F() expression to handle view count:

Post.objects.filter(pk=post.pk).update(views=F('views') + 1)
Enter fullscreen mode Exit fullscreen mode

Bad Approach!

By using F() and update views every time when user clicks on object is not good solution to create view counter. So, it will not count clicks properly, views will increase every time when same user clicks to same post.

Let me introduce you django-hitcount. Django-Hitcount allows you to track the number of hits (views) for a particular object. This isn’t meant to be a full-fledged tracking application or a real analytic tool; it’s just a basic hit counter.

Hitcounter will detect IPs and prevent from unreal views. So, views will count once for each specific user.

Create new Django project named "blog" and create app named "posts". Then run the following command to install the package.

pip3 install django-hitcount
Enter fullscreen mode Exit fullscreen mode

Add django-hitcount to your INSTALLED_APPS:


Enter fullscreen mode Exit fullscreen mode

There are several strategies for using django-hitcount but in this tutorial I will show you the best way to implement it in your app. Now, let's create our models:


from django.db import models
from hitcount.models import HitCountMixin, HitCount
from django.contrib.contenttypes.fields import GenericRelation
from django.utils.encoding import python_2_unicode_compatible

class Post(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField()
    published = models.DateField(auto_now_add=True)
    slug = models.SlugField(unique=True, max_length=100)
    hit_count_generic = GenericRelation(HitCount, object_id_field='object_pk',

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        return super(Post, self).save(*args, **kwargs)
Enter fullscreen mode Exit fullscreen mode

You are not required to do anything specific with your models; django-hitcount relies on a GenericForeignKey to create the relationship to your model’s HitCount.

Then, let's create our views:


from django.shortcuts import render
from django.views.generic.list import ListView
from hitcount.views import HitCountDetailView
from .models import Post

class PostListView(ListView):
    model = Post
    context_object_name = 'posts'
    template_name = 'post_list.html'

class PostDetailView(HitCountDetailView):
    model = Post
    template_name = 'post_detail.html'
    context_object_name = 'post'
    slug_field = 'slug'
    # set to True to count the hit
    count_hit = True

    def get_context_data(self, **kwargs):
        context = super(PostDetailView, self).get_context_data(**kwargs)
        'popular_posts': Post.objects.order_by('-hit_count_generic__hits')[:3],
        return context
Enter fullscreen mode Exit fullscreen mode

The HitCountDetailView can be used to do the business-logic of counting the hits by setting count_hit=True. Also we can filter the most viewed posts as shown above.

Now, let's configure our urls:


from django.contrib import admin
from django.urls import path, include
from posts.views import PostListView, PostDetailView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', PostListView.as_view(), name='posts'),
    path('<slug:slug>/', PostDetailView.as_view(), name='detail'),
    path('hitcount/', include(('hitcount.urls', 'hitcount'), namespace='hitcount')),
Enter fullscreen mode Exit fullscreen mode

To display total views for related object we will use get_hit_count template tag.


{% extends 'base.html' %}
{% load hitcount_tags %}

{% block content %}
  <h2>Posts List</h2>
    {% for post in posts %}
        <h3 class="mt-5"><a href='{% url "detail" post.slug %}'>{{post.title}}</a></h3>
        <p class="lead">{{post.description}}</p>
        <p>Views: {% get_hit_count for post %}</p>
    {% endfor %}
{% endblock %}
Enter fullscreen mode Exit fullscreen mode


{% extends 'base.html' %}
{% load hitcount_tags %}

{% block content %}
        <p class="lead">{{post.description}}</p>
        <p>Published: {{post.published}}</p>
        <p>Views: {% get_hit_count for post %}</p>

  <h3>Popular Posts</h3>
  {% for p in popular_posts %}
  {% endfor %}
{% endblock %}
Enter fullscreen mode Exit fullscreen mode

You can download or clone the project on my GitHub

GitHub logo raszidzie / Django-Hitcount-Tutorial

Simple Blog App using django-hitcount package


Simple Blog App using django-hitcount package

Get Started

Install dependencies by following commad:

pip3 install requirements.txt

and run the project

python3 manage.py makemigrations posts
python3 manage.py migrate
python3 manage.py runserver

That's it! Make sure you are following me on social media and please support me by buying me a coffee☕ so I can upload more tutorials like this. See you in next post DEVs!

Reverse Python


Editor guide
sajjadafridi profile image
Muhammad Sajjad

After python mange.py migrate
i get this error
_mysql.connection.query(self, query)
django.db.utils.OperationalError: (1170, "BLOB/TEXT column 'object_pk' used in key specification without a key length")

mahmudulhassan5809 profile image
Mahmudul Hassan

Did you solved this error??

codesnail profile image
CodeSnail 🐌

Ok worked!! but how to test it. Initially showing 0. I opened my post but count not increase

ybastan profile image

same problem here. Still 0 (zero) count is not increasing.

codesnail profile image
CodeSnail 🐌
class PostDetail(HitCountDetailView):
    model = Post
    context_object_name = "post"
    template_name = "awesomeposts/post_detail.html"
    count_hit = True

    def get_object(self):
        username = self.kwargs.get("username")
        post = self.kwargs.get("post")
        return get_object_or_404(
Enter fullscreen mode Exit fullscreen mode

do like this

Thread Thread
ybastan profile image

I don't know why but it didn't worked for me. Still 0 (zero)

bos1313 profile image

Great tutorial and it works fin with Sqlite database but when I try to use it with MySQL database I got error when do migration
150 "Foreign key constraint is incorrectly formed")')
I use user field as well
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, on_delete=models.CASCADE)

samatuulu profile image

How I can get the number views of one object in django shell?
I am getting error that says:
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'GenericRelatedObjectManager' object has no attribute 'hits'

for this error the query is: john_wick.hit_count_generic.hits

john_wick is Movie instance. And my model is

class Movie(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(max_length=2000)
image = models.ImageField(upload_to='movie_upload', null=False, blank=False)
year_of_production = models.IntegerField()
iframe = models.CharField(max_length=1500, verbose_name='iframe src')
hit_count_generic = GenericRelation(HitCount, object_id_field='object_pk',
created_at = models.DateTimeField(auto_now_add=True)

Please help me figure out.

gamino97 profile image

For those that have the error "(errno: 150 "Foreign key constraint is incorrectly formed")')", I've found an improvise solution, simply go to the installation folder of django-hitcount named "hitcount", go to the migrations folder, and erase everything except the init.py, run python manage.py makemigrations and python manage.py migrate and it's solved, sorry my bad English

billy_de_cartel profile image
Billy Okeyo

Can't i run it without python 2

crow_pigeon_sl profile image
Crow Pigeon

run only in Django 2x

cavinblake profile image

hi, will it work with the autoplay videos. Can i work with it..if a video autoplays the view will be counted for that post