ユーザー認証のいらない非同期通信いいねボタン
いいねボタンを作りたい。
でも、ここのようなマイナーなサイトだと、わざわざユーザー登録してまでいいねボタンを押す物好きはいないだろう。
じゃあ、ユーザー認証のいらないボタンを作ろう。連打防止機能欲しい。
そんな考えで生まれたボタンがこちら。
と言っても、これはただの画像なので、実際に押してみたい方はページ末尾へ。
ページ末尾へ移動
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;
}
終わりに
ざっくり説明でしたがいかがでしょうか。
需要があれば、もう少し詳しく書きたいなと思っています。