【问题标题】:Hit counter for Django blog postDjango 博客文章的计数器
【发布时间】:2023-03-26 15:40:01
【问题描述】:

在我寻找一种在没有任何第三方库的情况下为我的博客文章添加点击计数器的方法时,我找到了this answer on *

但是,由于我不是 Django 专家,我无法弄清楚如何在我的视图中使用该 Mixin。

这是我的模型的定义方式:

class Post(models.Model):
    STATUS_CHOICES = (('draft', 'Draft'), ('published', 'Published'))
    title = models.CharField(max_length=250)
    slug = models.SlugField(max_length=250, unique_for_date='publish')
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
    body = models.TextField()
    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')

还有我的看法:

def post_list(request):
    posts = Post.published.all()
    return render(request, 'blog/post/list.html', {'posts': posts})


class PostDetailView(DetailView):
    model = Post
    context_object_name = 'post'

这是该答案中提供的 mixin:

class BlogPostCounterMixin(object):
    def get_context_data(self, **kwargs):
        context = super(BlogPostCounterMixin, self).get_context_data(**kwargs)
        blog_post_slug = self.kwargs['slug']
        if not blog_post_slug in self.request.session:
            bp = BlogPost.objects.filter(slug=blog_post_slug).update(counter=+1)
            # Insert the slug into the session as the user has seen it
            self.request.session[blog_post_slug] = blog_post_slug
    return context

我会询问提供该答案的用户,但他已超过 2 年不活动。

感谢您的帮助。

【问题讨论】:

    标签: django django-views


    【解决方案1】:

    您可以在模型中创建一个名为viewsIntegerField

    然后在您的 post_detail 视图中,您可以在 return 语句之前执行此操作

    post.views += 1
    post.save(update_fields=['views'])
    

    显然,这种解决方案的缺点是错过了恰好在同一时刻发生的某些视图。

    编辑:

    在使用 mixin 之前,您必须首先使用基于类的视图而不是基于函数的视图,然后您可以使用此 mixin,在您的情况下,您可能希望使用 DetailView

    https://docs.djangoproject.com/en/3.2/ref/class-based-views/generic-display/#detailview

    class BlogPostCounterMixin:
        def get_object(self, *args, **kwargs):
            # get_object will be available if you use a DetailView
            obj = super().get_object(*args, **kwargs):
            post_unique_key = 'post_%s' % obj.pk # or whatever unique key is
            if not post_unique_key in self.request.session:
                obj.views += 1
                obj.save(update_fields=['views'])
                self.request.session[post_unique_key] = post_unique_key
    
            return obj
    

    并且可以这样使用

    class PostDetailView(BlogPostCounterMixin, DetailView):
        model = Post
        context_object_name = 'post'
    

    【讨论】:

    • 谢谢。我在问如何整合 Mixin 和我的观点。我不是在寻找任何其他解决方案。
    • 再次感谢。正如我提到的,我对 mixins 不太熟悉。我的问题是如何“调用”它——如果它应该被调用。我还将我的观点转换为 CBV 并更新了我原来的问题。
    • 你刚刚解决了我的问题,还教了我什么是 mixin 以及如何使用它。谢谢。