【问题标题】:How to increase the visits only the first time the user accesses the page?如何仅在用户第一次访问页面时增加访问量?
【发布时间】:2019-08-05 23:15:42
【问题描述】:

我想做以下事情:每次用户输入一篇文章,都会增加访问次数+1,但只是用户第一次登录,所以我必须保存用户已经输入的事实页面在某个地方。但我没有使用身份验证或类似的东西。

我知道我可以使用 javascript 在 LocalStorage 中存储,但我仍然不知道如何在后端使用 APIS。

在后端执行此操作的最简单方法是什么?

目前递增的函数如下。注意:我创建了一个新对象而不是使用“instance.visits + = 1”之类的东西,因为我需要保存每次访问的日期以过滤在特定时间段内访问次数更多的帖子,这是唯一的方法我明白了。

class ArticlePage(Page):
    # ....

    def serve(self, request, *args, **kwargs):
        request.is_preview = getattr(request, 'is_preview', False)

        self.views.create(date=datetime.datetime.now())
        self.save()
        print(self.views.all().count())

        return TemplateResponse(
            request,
            self.get_template(request, *args, **kwargs),
            self.get_context(request, *args, **kwargs)
        )

class ArticlePageViews(models.Model):
    article = models.ForeignKey(
        ArticlePage,
        on_delete=models.CASCADE,
        related_name='views'
    )
    date = models.DateTimeField()

    def __str__(self):
        return f'{self.date}'

【问题讨论】:

  • 你想只统计登录用户或任何用户的浏览量吗?
  • @Pedro 任何用户,如果它只是登录用户,将其存储在数据库中会容易得多。
  • 只在用户浏览器中存储 cookie。所以如果 coockie 存在,他已经第一次访问了 else

标签: django wagtail


【解决方案1】:

由于您只希望每个用户有一个视图,因此您不能将视图存储在用户会话中,因为用户登录时会话会发生变化。我建议您在用户第一次访问您的网站时设置一个 UUID cookie并设置一个较长的有效期,比如 10 年。这可以通过中间件来完成:

# middleware.py
import uuid


class UUIDMiddleware:
    """
    Middleware to set a UUID cookie when a user visits
    for the first time.
    """
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if not request.COOKIES.get('user_uuid'):
            user_uuid = str(uuid.uuid4())
            # set cookie in request so it can be used on the first visit
            request.COOKIES['user_uuid'] = user_uuid

            response = self.get_response(request)

            max_age = 60 * 60 * 24 * 365 * 10  # 10 years
            response.set_cookie('user_uuid',  user_uuid, max_age=max_age)
            return response

        return self.get_response(request)

记得将您的中间件添加到设置中。现在在您的 ArticlePageViews 模型中,您可以设置一个 unique_together 约束:

class ArticlePageViews(models.Model):
    article = models.ForeignKey(
        ArticlePage,
        on_delete=models.CASCADE,
        related_name='views'
    )
    user_uuid = models.UUIDField()
    date = models.DateTimeField(auto_now_add=True)  # set datetime automatically

    class Meta:
        unique_together = ('article', 'user_uuid')

    def __str__(self):
        return f'{self.date}'

在你看来(只是一个例子):

def article_view(request, article_id):
     article = get_object_or_404(ArticlePage, pk=article_id)
     user_uuid = request.COOKIES.get('uuid_cookie')
     if user_uuid is not None:  # user_uuid may not be set yet
         try:
             ArticlePageViews.objects.create(article=artricle, user_uuid=user_uuid)
         except IntegrityError:
             #  unique_together validation failed, so the user already viewed this article
             pass  # don't do anything
     ...

【讨论】:

  • 您也可以将uuid存储在模型中以确保它不会重复,但机会很少。
【解决方案2】:

这是使用 cookie 的可能性

class ArticlePage(Page):
    # ....

    def serve(self, request, *args, **kwargs):
        request.is_preview = getattr(request, 'is_preview', False)
        if not 'cookie_name' in request.COOKIES:
          self.views.create(date=datetime.datetime.now())
          self.save()
        print(self.views.all().count())

        response=TemplateResponse(
            request,
            self.get_template(request, *args, **kwargs),
            self.get_context(request, *args, **kwargs)
        )
        response.set_cookie('cookie_name', 'cookie_value')
        return response

参考this设置coockie的过期时间

【讨论】:

    猜你喜欢
    • 2014-09-18
    • 1970-01-01
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 2013-03-19
    • 2023-04-02
    • 2019-04-13
    相关资源
    最近更新 更多