如何对每个条目分别进行访问计数



你好,我正在制作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

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

如果您想要跟踪每个用户的总访问次数,您将需要让访问数据持久化。您可以使用一个额外的模型来实现这一点,例如,当(注册)用户访问页面时,每次都会创建一个新记录,或者我们可以使用一个简单的计数器。如果我们想防止同一个用户多次访问同一个对象时被计算多次,那么对用户使用ManyToManyField更有意义。

选项1:简单IntegerField

一个简单的实现,只计算访问次数,因此,如果同一个用户访问对象两次,则计算两次,可以使用额外的IntegerField来计算访问次数,如下所示。我们可以为此编写一个抽象模型:

class WithVisitCounter(models.Model):
visits= models.IntegerField(editable=False, default=0)
class Meta:
abstract = True

,然后让模型继承:

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

那么我们就可以得到一个mixinWithVisitCounterMixin:

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.visits = F('visits') + 1
obj.save(updated_fields=['visits'])
obj.visits = old_visit + 1
return obj
def get_context_data(self, *args, **kwargs):
cd = super().get_context_data(*args, **kwargs)
cd['visits'] = self.object.visits
return cd

然后我们可以在所有具有SingleObjectMixin(如DetailViewUpdateView)的视图中使用此Mixin:

class BlogPostDetailView(WithVisitCounterMixin,DetailView):
# ⋮

这将把访问者的数量作为visits传递给上下文数据,所以你可以用{{ visits }}来呈现它,如果对象被传递给模板的话,也可以用{{ object.visits }}来呈现。

选项2:用户模型的ManyToManyField

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

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

from django.conf import settings
classWithVisitCounter(models.Model):
visitors = models.ManyToManyField(
to=settings.AUTH_USER_MODEL,
related_name='%(model_name)s_visits'
)
class Meta:
abstract = True
class BlogPost(WithVisitCounter,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.visitors.add(self.request.user)
return obj
def get_context_data(self, *args, **kwargs):
cd = super().get_context_data(*args, **kwargs)
cd['visits'] = self.object.visitors.count()
return cd
对于该单个对象,我们可以通过计算self.object.visitors的记录数来获得访问者。

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

class BlogPostDetailView(WithVisitCounterMixin, DetailView):
# ⋮

我们可以再次使用{{ visits }}作为该项目的访客数量。

最新更新