Evgenii Legotckoi
Evgenii LegotckoiMarch 19, 2023, 10:56 a.m.

Django - Tutorial 061. Adding a Unique View Count

At the very beginning of creating articles and questions on the forum, I added a simple counter of views on this content.
This counter was an ordinary field of integer type and each time a page was requested it was incremented by one.
But not so long ago, I replaced this counter with a counter model for registering unique views. I just did it because I think it's prettier.

The counter counts unique visitors either by IP address, if the user is not authorized on the site, or by user account, if this user is authorized on the site.

So let's learn how to do it.

Viewer model

Responsible for counting unique users who viewed the site.

class Viewer(models.Model):
    ipaddress = models.GenericIPAddressField("IP address", blank=True, null=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True)

As you can see, there are only two fields in this model, the first is the IP Address, and the second is the foreign key to the user model

Adding a counter to the content model

And now let's add a counter to some site content model, for example, to the article model Article

class Article(models.Model):
    viewers = models.ManyToManyField(Viewer)

    # Some another code

Adding code is done as a Many-To-Many relationship. Since the unique visitor in this case will be one, but he can view many other articles. At the same time, the article can be viewed by many other users.

How to increase the content view counter

Most likely, some view class or view function will be responsible for displaying articles on your site. Personally, I prefer to use modern Class Based View in Django.

Therefore, I will write a mixin that can be used with DetailView to register unique views of content on the site.

class CountViewerMixin:

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        if hasattr(self.object, 'viewers'):
            viewer, created = Viewer.objects.get_or_create(
                ipaddress=None if request.user.is_authenticated else get_client_ip(request),
                user=request.user if request.user.is_authenticated else None
            )

            if self.object.viewers.filter(id=viewer.id).count() == 0:
                self.object.viewers.add(viewer)

        return response

It can be seen from the code that the mixin overrides the get method, checks that the content object exists in the View and only after that gets a unique visitor, and after checking that the visitor does not yet exist among the visitors who have viewed the content, adds it to the content views.

Thus, the content object itself is not modified, unlike the counter in the form of an integer field in the content model. What can actually complicate the code is if you have content model save method overrides or you have written receiver functions to handle save signals from the model. In the case of the Viewer counter, which is presented in this article, signals such as post_save on the content model simply do not work.

In the Content View, the mixin connection will look like this:

class ArticleView(CountViewerMixin, DetailView):
    # some another code

Usage in template

Inside the template, you can get the number of views as follows

{{ object.viewers.count }}

get_client_ip

The mixin also has a function to get an ip address from an HTTP request. I have already described this special function for getting the user's ip address from a request in one of the articles .

And in my latest revision for Django 3, it looks like this.

def get_client_ip(request):
    """
    Get client ip address from HTTP request

    :param request: HTTP request
    :return: IP Address
    """
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    return x_forwarded_for.split(',')[-1].strip() if x_forwarded_for else request.META.get('REMOTE_ADDR')

Conclusion

Such a counter will make it easier to maintain the code if you have reactions to saving content, and will also reduce the impact of cheats on content counters.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

Comments

Only authorized users can post comments.
Please, Log in or Sign up
МВ

Qt - Test 001. Signals and slots

  • Result:68points,
  • Rating points-1
ЛС

C++ - Test 001. The first program and data types

  • Result:53points,
  • Rating points-4
АА

C++ - Test 001. The first program and data types

  • Result:60points,
  • Rating points-1
Last comments
ИМ
Игорь МаксимовOct. 5, 2024, 7:51 p.m.
Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5July 5, 2024, 11:02 p.m.
QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrFeb. 9, 2024, 7:43 a.m.
Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVADec. 25, 2023, 11:30 p.m.
Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Now discuss on the forum
K
KeithfapOct. 13, 2024, 9:24 p.m.
добавить qlineseries в функции North Symbol by Bubnov Ltd https://seven-elephants.com/en/categories/penthouse/ Искеле – жемчужина острова! Все факторы говорят про большой инвестиционный потенциал данного района как для …
JW
Jhon WickOct. 2, 2024, 3:52 a.m.
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл ГусаревSept. 27, 2024, 9:09 p.m.
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
FynjyJuly 22, 2024, 4:15 p.m.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Follow us in social networks