跟踪对象的"页面浏览量"或"点击量"的数量?

tho*_*mad 36 django views

我确信有人在那里有一个可插拔的应用程序(或教程)近似于此,但我找不到它:我希望能够跟踪特定对象的"视图"数量(就像这里的问题一样)在stackoverflow上有一个"查看计数").

如果用户未登录,我不介意尝试放置cookie(或记录IP),以便他们不会通过刷新页面而无意中运行视图计数; 如果用户已登录,则只允许他们跨会话/浏览器/ IP地址进行一次"查看".我认为我不需要任何比这更好的东西.

我认为最好的方法是使用与我想要跟踪的各种模型分离并使用F表达式(各种类型)的中间件 - 其他关于stackoverlow的问题已提到这个(1)(2)(3) .

但是我想知道这个代码是否已经存在于野外 - 因为我不是最精明的编码器,我相信有人可以做得更好.微笑.

你看到了吗?

tho*_*mad 48

我不确定它是否最适合回答我自己的问题,但经过一些工作后,我整理了一个能够认真解决问题的应用程序:django-hitcount.

您可以在文档页面上阅读有关如何使用它的信息.

对于Django的hitcount的想法既来自我的两个原始答案(来到Teebes -和- vikingosegundo),这真的让我开始思考整个事情.

这是我第一次尝试与社区共享可插拔应用程序,并希望其他人发现它有用.谢谢!

  • Hitcount对于这项任务似乎过于复杂.特别是使用模型来计算命中数可能非常重.我建议(就像我在我的项目中所做的那样)使用Cache代替.智能缓存名称+超时正在很好地处理问题,而且速度非常快. (5认同)

Tee*_*bes 23

你应该使用django内置的会话框架,它已经为你做了很多这样的事情.我通过以下方式使用Q&A应用程序实现了这一点,我想跟踪视图:

在models.py中:

class QuestionView(models.Model):
    question = models.ForeignKey(Question, related_name='questionviews')
    ip = models.CharField(max_length=40)
    session = models.CharField(max_length=40)
    created = models.DateTimeField(default=datetime.datetime.now())
Run Code Online (Sandbox Code Playgroud)

在views.py中:

def record_view(request, question_id):

    question = get_object_or_404(Question, pk=question_id)

    if not QuestionView.objects.filter(
                    question=question,
                    session=request.session.session_key):
        view = QuestionView(question=question,
                            ip=request.META['REMOTE_ADDR'],
                            created=datetime.datetime.now(),
                            session=request.session.session_key)
        view.save()

    return HttpResponse(u"%s" % QuestionView.objects.filter(question=question).count())
Run Code Online (Sandbox Code Playgroud)

Vikingosegundo可能是正确的虽然使用内容类型可能是更可重用的解决方案,但绝对不会重新发明跟踪会话,Django已经这样​​做了!

最后,您可能应该拥有记录命中的视图,可以通过Ajax或css链接调用,以便搜索引擎不会增加您的计数.

希望有所帮助!


Vik*_*ica 11

我重申了我的想法,我已经写过这个问题的答案了,其中没有引起任何注意:D

你可以创建一个通用的Hit模型

class Hit(models.Model):
    date = models.DateTimeField(auto_now=True)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
Run Code Online (Sandbox Code Playgroud)

在你的view.py中你写这个函数:

def render_to_response_hit_count(request,template_path,keys,response):
    for  key in keys:
        for i in response[key]:
             Hit(content_object=i).save()
    return render_to_response(template_path, response)
Run Code Online (Sandbox Code Playgroud)

以及您感兴趣的观点

return render_to_response_hit_count(request,   'map/list.html',['list',],
        {
            'list': l,
        })
Run Code Online (Sandbox Code Playgroud)

这种方法不仅可以计算命中数,还可以按时间,内容类型等过滤命中历史记录,从而为您提供强大功能.

由于命中表可能会快速增长,您应该考虑删除策略.

代码未经测试


Rad*_*ico 6

我知道这个问题既旧又棘手还提供了一个应用程序来解决问题并启发我解决方案。我想分享此解决方案,因为我没有找到太多有关此主题的信息,它可能会对其他人有所帮助。我的方法是基于视图路径(URL)使通用模型可用于任何视图。

models.py

class UrlHit(models.Model):
    url     = models.URLField()
    hits    = models.PositiveIntegerField(default=0)

    def __str__(self):
        return str(self.url)

    def increase(self):
        self.hits += 1
        self.save()


class HitCount(models.Model):
    url_hit = models.ForeignKey(UrlHit, editable=False, on_delete=models.CASCADE)
    ip      = models.CharField(max_length=40)
    session = models.CharField(max_length=40)
    date    = models.DateTimeField(auto_now=True)
Run Code Online (Sandbox Code Playgroud)

views.py

def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

def hit_count(request):
    if not request.session.session_key:
        request.session.save()
    s_key = request.session.session_key
    ip = get_client_ip(request)
    url, url_created = UrlHit.objects.get_or_create(url=request.path)

    if url_created:
        track, created = HitCount.objects.get_or_create(url_hit=url, ip=ip, session=s_key)
        if created:
            url.increase()
            request.session[ip] = ip
            request.session[request.path] = request.path
    else:
        if ip and request.path not in request.session:
            track, created = HitCount.objects.get_or_create(url_hit=url, ip=ip, session=s_key)
            if created:
                url.increase()
                request.session[ip] = ip
                request.session[request.path] = request.path
    return url.hits
Run Code Online (Sandbox Code Playgroud)

  • 谢谢Radico。我已经在您的网站上使用了您的方法,并且效果非常好。我在基于类的视图中使用它:) (2认同)

Pan*_*hra 5

我通过创建一个模型 PageViews 并在其中创建一个“Hits”列来做到这一点。每次点击主页网址时。我增加了 Hit 列的第一行也是唯一行,并将其呈现给模板。这是它的外观。

视图.py

def Home(request):

    if(PageView.objects.count()<=0):
        x=PageView.objects.create()
        x.save()
    else:
        x=PageView.objects.all()[0]
        x.hits=x.hits+1
        x.save()
    context={'page':x.hits}
    return  render(request,'home.html',context=context)
Run Code Online (Sandbox Code Playgroud)

模型.py

class PageView(models.Model):
    hits=models.IntegerField(default=0)
Run Code Online (Sandbox Code Playgroud)