django - 如何对每个项目单独进行访问计数

标签 django hitcounter visitor-statistic

您好,我正在制作 django 应用程序,我想添加访问计数器功能,但每个项目都是单独的。我认为这将是一个很好的功能。

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['comments'] = Comment.objects.filter(item=self.object)
        context['form'] = CommentCreationForm()
        num_visits = self.request.session.get('num_visits', 0)
        self.request.session['num_visits'] = num_visits + 1
        context['visits'] = num_visits
        return context

最佳答案

目前您正在实现的是每个 session 一个计数器。事实上,这意味着如果用户在您的页面上启动 session ,他们首先会看到零,然后是一个,依此类推。但这只会计算用户在 session 中访问页面的次数。其他用户的访问不会产生任何影响。

如果您想跟踪每个用户的总访问次数,则需要保留访问数据。您可以使用额外的模型来做到这一点,例如,当(注册)用户访问页面时每次都会创建一条新记录,或者我们可以使用一个简单的计数器。如果我们想防止同一用户多次访问同一个对象而对其进行多次计数,那么对用户使用 ManyToManyField 更有意义。

选项 1:简单的IntegerField

一个简单的实现,简单地计算访问次数,因此如果用户访问该对象两次,则对同一用户进行两次计数,可以使用额外的 IntegerField 来实现,以计算访问次数,这好像。我们可以为此编写一个抽象模型:

class WithVisitCounter(models.Model):
    <strong>visits</strong> = models.IntegerField(editable=False, default=0)

    class Meta:
        <strong>abstract = True</strong>

然后让模型继承于此:

class BlogPost(WithVisitCounter, models.Model):
    # ⋮

然后我们可以制作一个mixin WithVisitCounterMixin:

from django.views.generic.detail import SingleObjectMixin

class WithVisitCounterMixin(SingleObjectMixin):

    def get_object(self, *args, **kwargs):
        obj = super().get_object(*args, **kwargs)
        old_visit = obj.visits
        obj<b>.visits = F('visits') + 1</b>
        obj.save(<b>updated_fields=['visits']</b>)
        obj.visits = old_visit + 1
        return obj

    def get_context_data(self, *args, **kwargs):
        cd = super().get_context_data(*args, **kwargs)
        <b>cd['visits'] = self.object.visits</b>
        return cd

然后我们可以在所有具有 SingleObjectMixin 的 View 中使用这个 Mixin,例如 DetailViewUpdateView :

class BlogPostDetailView(<strong>WithVisitCounterMixin,</strong> DetailView):
    # ⋮

这会将访问者数量作为 visits 传递给上下文数据,因此您可以使用 {{ attempts }}{{ 来呈现此数据object.visits }} 如果对象被传递给模板。

选项 2:用户模型的 ManyToManyField

第一个选项不考虑多次访问同一对象的用户。这意味着同一用户可以访问该页面二十次,这将被视为二十次独立访问。

在这种情况下,我们可以定义一个抽象模型,为用户添加链接,其中:

from django.conf import settings

class <strong>WithVisitCounter</strong>(models.Model):
    visitors = models.ManyToManyField(
        to=settings.AUTH_USER_MODEL,
        related_name='%(model_name)s_visits'
    )

    class Meta:
        <strong>abstract = True</strong>

class BlogPost(<strong>WithVisitCounter,</strong> models.Model):
    # ⋮

然后我们可以定义一个WithVisitCounterMixin,就像我们为第一个选项所做的那样。在本例中,我们将添加从对象到登录用户的链接:

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.detail import SingleObjectMixin

class WithVisitCounterMixin(SingleObjectMixin):

    def get_object(self, *args, **kwargs):
        obj = super().get_object(*args, **kwargs)
        obj<strong>.visitors.add(</strong>self.request.user<strong>)</strong>
        return obj

    def get_context_data(self, *args, **kwargs):
        cd = super().get_context_data(*args, **kwargs)
        <strong>cd['visits'] = self.object.visitors.count()</strong>
        return cd

对于该单个对象,我们可以通过计算 self.object.visitors 的记录数来获取访问者。

因此,我们也可以在 DetailViewUpdateView 中使用该 mixin:

class BlogPostDetailView(WithVisitCounterMixin, DetailView):
    # ⋮

然后我们可以再次使用 {{ attempts }} 来表示该项目的访问者数量。

关于django - 如何对每个项目单独进行访问计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68975589/

相关文章:

ruby-on-rails - 保存特定操作的请求

HTML 在 Django 中无法正确呈现

python - 如何从django数据库中获取对象?

django - 自定义日期聚合函数

php - 如何构建动态访客计数器

html - 记录/识别来自特定事件的访问者

Django - PUT/DELETE 请求中存储的参数在哪里?

PHP 多个客户端访问同一文件

hitcounter - 如何在不增加点击计数器的情况下访问网页?

javascript - 使用 PHP 打开图片文件时防止新 session