目前您正在实施的是每个会话的计数器。实际上,这意味着如果用户在您的页面上启动会话,首先他们将看到零,然后是一个,依此类推。但这只会计算用户在会话中访问页面的次数。其他用户的访问不会产生任何影响。
如果您想跟踪每个用户的总访问次数,则需要让访问数据保持不变。您可以使用额外的模型来做到这一点,例如,每次(注册)用户访问页面时都会创建一条新记录,或者我们可以使用简单的计数器。如果我们想防止在多次访问同一个对象时多次计算同一个用户,那么ManyToManyField
对用户使用 a 更有意义。
选项1:简单IntegerField
一个简单地计算访问次数的简单实现,因此如果该用户访问该对象两次,则将同一用户计算两次,可以通过额外IntegerField
的计算访问次数来实现,如下所示。我们可以为此编写一个抽象模型:
class WithVisitCounter(models.Model):
visits = models.IntegerField(editable=False, default=0)
class Meta:
abstract = True
然后让模型继承自:
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.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
然后我们可以Mixin
在所有有SingleObjectMixin
aDetailView
和 an 的视图中使用它UpdateView
:
class BlogPostDetailView(WithVisitCounterMixin, DetailView):
# ⋮
这会将访问者的数量传递visits
给上下文数据,因此您可以使用{{ visits }}
,或者{{ object.visits }}
如果将对象传递给模板,则可以使用 with 来呈现它。
选项2:AManyToManyField
到用户模型
第一个选项不考虑多次访问同一对象的用户。这意味着同一用户可以访问该页面二十次,这将被视为二十次独立访问。
在这种情况下,我们可以定义一个抽象模型,将链接添加到用户,其中:
from django.conf import settings
class WithVisitCounter(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
对于该单个对象,我们可以通过计算 的记录数来获取.visitors
访问者self.object
。
DetailView
因此,我们也可以在 a or中使用该 mixin UpdateView
:
class BlogPostDetailView(WithVisitCounterMixin, DetailView):
# ⋮
然后我们可以再次使用{{ visits }}
该项目的访问者数量。