はじめに
今回はDjangoで作ったWebサイトにaxiosを使っていいね機能が作れないかと調べてみました。
案の定、Ajaxを使うか画面リロード付きいいね機能の作り方しかなかったので、参考サイトを見ながらaxiosでいいね機能を作ってみました。
参考サイト
いいね機能を実装したサイトのチュートリアルサイト
いいね機能参考
本題
記事の順序に従って実装していきます。
この機能が欲しい人はそこそこコードを読めると信じているので簡単な説明は省きました。
Model.py
PostクラスなどはDjango Girls Tutorialのモデルを参照しています。
from django.db import models
from django.conf import settings
from django.utils import timezone
from django.contrib.auth.models import User #追加
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_at = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
like_num = models.IntegerField(default=0) #追加
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
以下コードがいいね機能モデル ↓追加
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='like_user')
post = models.ForeignKey(Post, on_delete=models.CASCADE)
View.py
今回はクラスベースで書いていますので、関数ベースで作りたい方は工夫してください
#like
#unlike
のJsonResponseの引数に関しては渡したいJsonデータを設定してください
class Like_Detail(View):
def get(self, request, pk, *args, **kwargs):
post = Post.objects.get(id=pk)
is_like = Like.objects.filter(user=self.request.user).filter(post=post).count()
# unlike
if is_like > 0:
liking = Like.objects.get(post__id=pk, user=self.request.user)
liking.delete()
post.like_num -= 1
post.save()
post = get_object_or_404(Post, pk=pk)
json = {'like_value': post.like_num} #ここのJsonデータに関してはご自由に
return JsonResponse(json)
# like
post.like_num += 1
post.save()
like = Like()
like.user = self.request.user
like.post = post
like.save()
post = get_object_or_404(Post, pk=pk)
json = {'like_value': post.like_num} #ここのJsonデータに関してはご自由に
return JsonResponse(json)
URL.py
from django.urls import path
from . import views
from .views import Like_Detail # View.pyで設定したクラス名をインポートさせてください
app_name = 'application' #アプリケーション名で合わせてください
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit/', views.post_edit, name='post_edit'),
path('post/<int:pk>/like/',Like_Detail.as_view(), name='get'), #追加
]
POST_Detail.html
最後に一番重要なHTML内のJavaScript処理について説明します。
< 記事サイトに飛んだ時の処理の流れです >
1.記事詳細ページに飛んだClientユーザーの情報をView.pyに渡す様に命令をします。
2.Javascript側にView.py側から渡されたClientユーザーがいいねしているか、していないかと記事の総合いいね数の情報を受け取ります。
3.もし、記事に対してユーザーがいいねをしていない場合は<input>
タグのclassにunlike
タグを追加します。(いいねしている場合はlike
を追加させる処理が書かれています。)
< いいねボタンが押された際の処理の流れです >
1.いいねボタンを押すとaxiosを利用して画面リロードなしてリクエストを送ります。
2.View.py側でユーザーの記事のいいね処理を行います。
3.HTML側ではJavascriptが押されたら数値を変更するので毎回View.py側からデータを受け取る必要がなくなることになります
{% extends 'application/base.html' %}
{% block content %}
<div class="post">
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% endif %}
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'application:post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<input type="button" value="Check" onclick="like()" id="like-data"> いいね<span id="like-count">{{ post.like_num }}</span>
<script>
var likeinfo = {{ is_like }};
var likecount = {{ post.like_num }};
window.onload = function () {
if (likeinfo > 0){
document.getElementById("like-data").classList.add("unlike");
}else{
document.getElementById("like-data").classList.add("like");
}
};
var like = function () {
const response = axios.get('/post/{{ post.pk }}/like/');
console.log(response);
console.log( document.getElementById('like-count').innerText);
if (likeinfo > 0){
likeinfo = likeinfo - 1;
likecount = likecount - 1;
document.getElementById('like-count').innerText=likecount;
}else{
likeinfo = likeinfo + 1;
likecount = likecount + 1;
document.getElementById('like-count').innerText=likecount;
}
document.getElementById("like-data").classList.toggle("unlike");
document.getElementById("like-data").classList.toggle("like");
}
</script>
{% endif %}
<h2>{{ post.title }}</h2>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endblock %}
補足 CSS
<input>
タグのclassにlike
やunlike
をタグで付け替える意味はいいねしている
か、してない
かでCSSのデザインを変更する設定をしているからです。
.unlike {
color:red;
}
.like {
color: black;
}
最後に
自分用に書いてはいますが、
参考になりましたらいいね👍よろしくお願いします。
色んな人に見ていただければ次回allauthに関しても書こうかなと思います。