3
3

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】axiosを使って自作Like機能を作ってみた

Last updated at Posted at 2020-03-10

はじめに

今回は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にlikeunlikeをタグで付け替える意味はいいねしているか、してないかでCSSのデザインを変更する設定をしているからです。
.unlike {
    color:red;
}
.like {
    color: black;
}

最後に

自分用に書いてはいますが、
参考になりましたらいいね👍よろしくお願いします。
色んな人に見ていただければ次回allauthに関しても書こうかなと思います。

3
3
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
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?