web-dev-qa-db-ja.com

オブジェクトの「ページビュー」または「ヒット」の数を追跡しますか?

これに近いプラグイン可能なアプリ(またはチュートリアル)が誰かにあると確信していますが、それを見つけるのに問題があります。特定のオブジェクトの「ビュー」の数を追跡できるようにしたい(ちょうどここの質問のように) stackoverflowには「ビュー数」があります)。

ユーザーがログインしていない場合は、Cookieを配置(またはIPを記録)しても、ページを更新して誤って表示回数を増やすことはできません。ユーザーがログインしている場合は、セッション/ブラウザー/ IPアドレス全体で1つの「ビュー」のみを許可します。それ以上に凝ったものは必要ないと思います。

これを行うための最良の方法は、追跡したいさまざまなモデルから切り離され、F式(一種)を使用するミドルウェアを使用することです-stackoverlowに関する他の質問はこれを暗示しています( 1 )( 2 )()。

しかし、私はこのコードがすでに一般に出回っているのではないかと思います-私は最も精通したコーダーではないので、誰かがもっとうまくやれると私は確信しているからです。スマイル。

見たことありますか?

37
thornomad

自分の質問に答えるのに最適かどうかはわかりませんが、少し作業した後、問題を真剣に解決するアプリを作成しました: Django-hitcount

使い方は ドキュメントページ で読むことができます。

Django-hitcountのアイデアは、私の2つの元の回答( Teebes -and- vikingosegundo )の両方から生まれたものであり、本当に全体を考え始めました。

これは、プラグイン可能なアプリをコミュニティと共有するための私の最初の試みであり、他の誰かがそれを役に立てば幸いです。ありがとう!

49
thornomad

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())

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())

Vikingosegundoはおそらく正しいですが、content-typeを使用する方がおそらくより再利用可能なソリューションですが、トラッキングセッションの観点からホイールを再発明しないでください。Djangoはすでにそうしています!

最後に、検索エンジンがカウントを更新しないように、ヒットを記録するビューをAjaxまたはcssリンク経由で呼び出す必要があります。

お役に立てば幸いです。

23
Teebes

一般的なヒットモデルを作成できます

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')

あなたの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)

そしてあなたが見たいと思う見解

return render_to_response_hit_count(request,   'map/list.html',['list',],
        {
            'list': l,
        })

このアプローチは、ヒットをカウントするだけでなく、時間、コンテンツタイプなどでヒット履歴をフィルタリングするためのパワーを提供します...

ヒットテーブルは急速に拡大している可能性があるため、削除戦略を検討する必要があります。

11
vikingosegundo

私はこの質問が古いものであることを知っています thornomad は問題を解決するためのアプリを置いており、私に解決策を教えてくれます。このトピックについてあまり情報が見つからなかったため、この解決策を共有したいと思います。他の人の役に立つかもしれません。私のアプローチは、ビューパス(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)

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
6
Radico

私はクッキーを使ってそれをしました。それをするのが良いかどうかわからない。次のコードは、すでに設定されているCookieが存在する場合は最初に検索し、存在しない場合はtotal_viewカウンターを増やし、存在しない場合はtotal_viewsとunique_viewsの両方を増やします。 total_viewsとunique_viewsはどちらもDjangoモデルのフィールドです。

def view(request):
    ...
    cookie_state = request.COOKIES.get('viewed_post_%s' % post_name_slug)
    response = render_to_response('community/post.html',context_instance=RequestContext(request, context_dict))
    if cookie_state:
        Post.objects.filter(id=post.id).update(total_views=F('total_views') + 1)
    else:
        Post.objects.filter(id=post.id).update(unique_views=F('unique_views') + 1)
        Post.objects.filter(id=post.id).update(total_views=F('total_views') + 1)
                        response.set_cookie('viewed_post_%s' % post_name_slug , True, max_age=2678400)
    return response
2
Mudit Jain

これを行うには、モデルのPageViewsを作成し、その中に列「ヒット」を作成します。ホームページのURLがヒットするたび。 Hit列の最初の唯一の行をインクリメントして、テンプレートにレンダリングします。ここではそれがどのように見えるか。

Views.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)

Models.py

class PageView(models.Model):
    hits=models.IntegerField(default=0)
2
Pankaj Mishra