2021.02.18  

【Django】JavaScriptでいいねボタンの作成(ユーザー認証無し)

Django    

ユーザー認証のいらない非同期通信いいねボタン

いいねボタンを作りたい。
でも、ここのようなマイナーなサイトだと、わざわざユーザー登録してまでいいねボタンを押す物好きはいないだろう。
じゃあ、ユーザー認証のいらないボタンを作ろう。連打防止機能欲しい。

そんな考えで生まれたボタンがこちら。
と言っても、これはただの画像なので、実際に押してみたい方はページ末尾へ。
ページ末尾へ移動

javascriptも採用しているので、ボタンを押してもページ遷移せずにカウントが増える仕様だ。

実装

実際のソースを紹介する。
解説についてはソースの中に記載しています。

models.py
class Post(models.Model):
    # ブログの記事
    title = models.CharField('タイトル',max_length=255)
    url = models.SlugField('URL名',unique=True)
    text = MarkdownxField('テキスト') # ここは今回の処理に関係なし
    created_at = models.DateTimeField('作成日',default=timezone.now)
    good = models.IntegerField('Good',default=0)  # 追加が必要な箇所。いいねの数を記事に紐づけて保存する

    def __str__(self):
        return self.title
post_detiail.html
<!--  Django 部分 -->
{% extends 'blog/base.html' %}
{% block content %}

     <div class="good-flame">
       <!-- onclick="api_good() を定義すると、GOODボタンを押した際以下で書いた
            JavaScript関数が実行される。<span id="good_count"></span>に
            追加されたいいねの数が反映される-->
       <a id="good-a" onclick="api_good()">GOOD <span id="good_count"></span></a>
     </div>


<!--  javascript 部分 -->

<script>  
   // ページが読み込まれた時にDBから記事に紐づいた「いいね」の数を取得する
  window.onload = function () {
      document.getElementById("good_count").innerText = {{ post.good }}
  }
  
  // api_good関数が設定されたaタグがクリックされたら、非同期通信でgoodのカウントを1増やし画面に結果を反映する
   function api_good() {
      // いいねの数を増やす記事idをJavaScriptに渡す処理
      var api_url = "{% url 'blog:api_good' post.pk %}";
      var btn = document.getElementById("good_count");
      // 非同期通信をするための関数をインタンス化する
      var request = new XMLHttpRequest();
      request.onreadystatechange = function () {
       // 非同期通信が完了したら以下のifが処理される。request.readyState === 4部分が非同期処理完了を意味している
          if (request.readyState === 4 && request.status === 200) {
              var received_data = JSON.parse(request.responseText);
             // 画面にいいねの数を反映する
              btn.innerText = received_data.good;
              // 画面をリロードするまでボタンを押せなくする処理
              document.getElementById("good-a").removeAttribute( "onclick" );
          }
      }
      // サーバーとの通信を実行する処理
      request.open("GET",api_url);
      request.send();
    }

</script>

{% endblock %}
post_detiail.html ※必要箇所意外は省略
app_name = 'blog'

urlpatterns = [
    path('api/good/<int:pk>/', views.ApiGoodView, name='api_good'),
]
veiws.py
from django.http import Http404
from django.http.response import JsonResponse

def ApiGoodView(request,pk):
    try:
        obj = Post.objects.get(pk=pk) # pkを元にPostテーブルの対象記事レコードを取得する
    except Post.DoesNotExist:
        raise Http404
    obj.good += 1  # ここでいいねの数を増やす
    obj.save()  # 保存をする

    return JsonResponse({"good":obj.good}) # いいねの数をJavaScriptに渡す
style.css ※ ボタンのデザイン。処理には直接影響なし。
/* Goodボタンのスタイル */
a#good-a {
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1.5;
  position: relative;
  display: inline-block;
  padding: 0.3rem 0.7rem;
  cursor: pointer;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  -webkit-transition: all 0.3s;
  transition: all 0.3s;
  vertical-align: middle;
  text-decoration: none;
  letter-spacing: 0.1em;
  border-radius: 0.5rem;
  border: 2px solid #55C500;
  border-radius: 0;
  background: #fff;
  color: #55C500;
  text-align: center;
}

a#good-a:hover {
  color: #fff;
  background: #55C500;
}

ページの上へ戻る

終わりに

ざっくり説明でしたがいかがでしょうか。
需要があれば、もう少し詳しく書きたいなと思っています。

コメント
現在コメントはありません。
コメントする
コメント入力

名前 (※ 必須)

メールアドレス (※ 必須 画面には表示されません)

送信