0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Djangoでクリック数(view数)カウント

Posted at

##はじめに
クリック数のカウント、具体的には投稿した記事に対するView数を表示する機能を、DjangoとJavascriptのajax通信を使って実装していきます。
こちらのサイトを参考にしています。

##カウントする部分

post_list.html
{% for post in posts %}
    <table>
      <div class="post">
         <div class="date">
              <p>{{ post.published_date }}</p>
           </div>
              <a class="post_{{ post.pk }}" href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a>
         {{ new.view_number }}views
        </div>
    </table>
{% endfor %}

Listviewでcontext_object_name ="posts" と宣言して、templateにPostmodelを渡しています。
そして、aタグに class="post_{{ post.pk }}" として、objectごとにpkを振ったクラス名を付けます。DetailViewを用いた各objectのpost_detailに遷移した回数をカウントしていきます。

ここで登場するPostmodelは

models.py
class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    title = models.CharField(max_length=50)
    text = MDTextField() 
    view_number = models.IntegerField(blank=False, default=0)
    created_date = models.DateTimeField(default=timezone.now)
    published_date = models.DateTimeField(blank=True, null=True)

の一般的な形です。
##カウント処理

count.js
$(function() {
//csrf_tokenの取得に使う
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

function csrfSafeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

for(let number =1;number<=1000;number ++){
    //post_1~post_1000まで、クリックした時の動作
    $('.post_'+number).click(function() {
        var csrf_token = getCookie("csrftoken");

        $.ajax({
            type: 'POST',
            url: './post_list',
            //渡したいdataを辞書形式で挿入
            data: {
                view_number: 1,
                post_number: number,  
            },
            contentType: "application/json",
            //csrftokenを付与
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrf_token);}
            },
            });
              
    });

};
});

Djangoでformを作るときに使う{% csrf_token %}をつけるための処理をする必要があるため、少しコードが長くなっています。上半分のコードの意味はよくわかりませんが、ここでは大丈夫そうです。
view_numberはrequestされるごとに1を足すだけなので、送るデータはpost_numberだけでも十分です。

views.py
from django.http import QueryDict

    if request.method == 'POST':
        # 送ったdataはrequest.bodyに入っている。
        dic = QueryDict(request.body, encoding='utf-8')
        number = int(dic.get('view_number'))
        post_number = int(dic.get('post_number'))
        
        viewed_post = get_object_or_404(Post, pk=post_number)
        viewed_post.view_number += number
        viewed_news.save()

request.bodyには view_number=1&post_number=(count.jsで送ったnumber) が入っています。QueryDictに関してはDjango公式を見ると理解できそうです。QueryDict(request.body)で辞書形式に変換してgetでkeyに対応する値を取得できます。
後はget_object_or_404(Post, pk=post_number)で遷移先のPostオブジェクトを取得し、view_numberに1を加算して、保存。

##おわりに
csrf_tokenの問題で混乱した箇所だったので残しておこうと思いました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?