Python 在Django中监控博客文章浏览量的最佳方法
我正在开发一个博客webapp,我想监控一篇文章的浏览量。我已经决定使用PostDetail视图进行计数。为了防止特定用户的计数器递增,我将只允许记录的用户计数,并且一个用户只能计数一次 这是我的贴身模特Python 在Django中监控博客文章浏览量的最佳方法,python,django,blogs,Python,Django,Blogs,我正在开发一个博客webapp,我想监控一篇文章的浏览量。我已经决定使用PostDetail视图进行计数。为了防止特定用户的计数器递增,我将只允许记录的用户计数,并且一个用户只能计数一次 这是我的贴身模特 class Post(models.Model): title = models.CharField(max_length=150) content = models.TextField(max_length=3000, null=True, blank=True) d
class Post(models.Model):
title = models.CharField(max_length=150)
content = models.TextField(max_length=3000, null=True, blank=True)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
viewers = models.TextField(default="", null=True, blank=True)
numViews = models.IntegerField(default=0)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
我基本上是使用一个字段“viewers”来跟踪已经统计过的用户,“numviews”作为计数器
My views.py函数
class PostDetailView(DetailView):
model = Post
def get(self, request, *args, **kwargs):
# increment post views whenever request is made
postObject = self.get_object()
user = request.user
if postObject.viewers == None:
postObject.viewers = ""
postObject.save()
if user.is_authenticated and user.username not in postObject.viewers:
# increment
postObject.numViews += 1
postObject.save()
# add username to viewers list
postObject.viewers+=user.username
postObject.save()
return super().get(request, *args, **kwargs)
在views函数中,我检查用户名是否已经附加到viewers字符串中,否则附加用户名并递增计数器。
有没有更有效的方法?如果博客获得数千个视图,那么它将是一个非常长的用户名字符串
如果博客获得数千个视图,那么它将是一个非常长的用户名字符串
它不仅效率低下,而且可能导致错误的结果。如果您有三个用户foo
、bar
和foobar
,那么如果foo
访问页面,并且bar
访问页面,那么如果foobar
访问页面,他们的视图将不被考虑
另一个问题是,这里可能存在竞争条件:如果两个用户几乎同时访问同一个帖子,那么数据库最终可能只为一个用户更新对象,因此就像另一个用户从未访问过页面一样
通常,您可以通过以下方式确定谁查看了帖子:
来自django.conf导入设置的
班级职务(models.Model):
title=models.CharField(最大长度=150)
content=models.TextField(最大长度=3000,null=True,blank=True)
发布日期=models.DateTimeField(默认值=时区.now)
author=models.ForeignKey(settings.AUTH\u USER\u MODEL,on\u delete=models.CASCADE)
viewers=models.ManyToManyField(
settings.AUTH\u用户\u模型,
相关的帖子
可编辑=假
)
定义(自我):
返回自己的标题
def get_绝对_url(自身):
返回反向('post-detail',kwargs={'pk':self.pk})
然后,我们可以将该视图实现为:
from django.db.models import Count
class PostDetailView(DetailView):
model = Post
queryset = Post.objects.annotate(
num_views=Count('viewers')
)
def get_context_data(self, *args, **kwargs):
if self.user.is_authenticated:
__, created = Post.viewers.through.objects.get_or_create(
post=self.object,
user=self.request.user
)
if created:
self.object.num_views += 1
return super().get_context_data(*args, **kwargs)
从django.db.models导入计数
类PostDetailView(DetailView):
型号=员额
queryset=Post.objects.annotate(
num_views=Count('viewers')
)
def获取上下文数据(self、*args、**kwargs):
如果self.user.u经过身份验证:
__,created=Post.viewers.through.objects.get\u或\u create(
post=self.object,
user=self.request.user
)
如果创建:
self.object.num_视图+=1
return super()。在post详细信息视图中,只有self.user->self.request.user进行了更正。此外,查看者的数量可以通过((post.viewers.count}})访问html模板中的一个post对象,也可以作为{object.num_views}}访问详细视图模板中的一个post对象无需使用get_或_create,根据“添加第二次是可以的,它不会复制关系:”。你可以简单地添加而不必思考。@AbdulAzizBarkat:是的,但我们需要知道是否应该增加num_视图(代码>:)这是包含它的唯一原因。你是对的,没有想到。:)它可以在基于函数的视图中完成吗?@Progam:是的,只需在函数中添加逻辑,self.object
就是您获取的对象。但是,与许多可重用逻辑一样,基于类的视图通常更好地混合在逻辑中。您传递给哪个变量
来访问post视图
<代码>查询集
或创建的
?
from django.db.models import Count
class PostDetailView(DetailView):
model = Post
queryset = Post.objects.annotate(
num_views=Count('viewers')
)
def get_context_data(self, *args, **kwargs):
if self.user.is_authenticated:
__, created = Post.viewers.through.objects.get_or_create(
post=self.object,
user=self.request.user
)
if created:
self.object.num_views += 1
return super().get_context_data(*args, **kwargs)