您好,我正在制作 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
,例如 DetailView
和 UpdateView
:
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
的记录数来获取访问者。
因此,我们也可以在 DetailView
或 UpdateView
中使用该 mixin:
class BlogPostDetailView(WithVisitCounterMixin, DetailView):
# ⋮
然后我们可以再次使用 {{ attempts }}
来表示该项目的访问者数量。
关于django - 如何对每个项目单独进行访问计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68975589/