DjangoでAPI&Nuxtでいいね機能を実装
以前、Djangoでいいね機能を実装したことがありましたが、今回Django Restful APIを使い、Nuxtの方でいいね機能を実装してみようと思います。
DjangoでAPIを作成
User APIはフォロー機能を実装した時のものを使おうと思います。こちらを参照ください。
Postモデル&Likeモデルはすでにできていると仮定します。できていなければ、上の"Djangoでいいね機能"を参照してください。Serializerを作っていきましょう。
from posts.models import Post, Like class PostMiniSerializer(serializers.ModelSerializer): class Meta: model = Post fields = ['id', 'text', 'background', 'date_created',] class PostWriteSerializer(serializers.ModelSerializer): likes_count = serializers.SerializerMethodField() is_liking = serializers.SerializerMethodField() class Meta: model = Post fields = ('id', 'background', 'text', 'date_created', 'likes_count', 'is_liking') def get_likes_count(self, obj): return obj.likes.count() def get_is_liking(self, obj): user = self.context['request'].user if user.is_authenticated: return Like.objects.filter(user=user, post=obj).exists() else: return False class PostReadSerializer(PostWriteSerializer): user = UserMiniSerializer() class Meta(PostWriteSerializer.Meta): fields = PostWriteSerializer.Meta.fields + ('user',)
permissions.pyにも付け足しておきましょう。
class IsPosterOrReadOnly(permissions.BasePermission): def has_object_permission(self, request, view, obj): if request.method in permissions.SAFE_METHODS: return True return obj.user == request.user
それではviewsetを書いていきましょう。
from django.db.models import Q from django.shortcuts import render from rest_framework import viewsets, filters, status, permissions, filters from rest_framework.response import Response from rest_framework.decorators import action from users.models import User, Connection from posts.models import Post, Like from .serializers import (UserSerializer, UserMiniSerializer, PostReadSerializer, PostWriteSerializer,) from .permissions import IsMyselfOrReadOnly, IsPosterOrReadOnly class PostViewSet(viewsets.ModelViewSet): queryset = Post.objects.all() permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsPosterOrReadOnly] filter_backends = [filters.SearchFilter] search_fields = ['text'] def get_serializer_class(self): if self.request.method in ['POST', 'PUT', 'PATCH']: return PostWriteSerializer return PostReadSerializer def perform_create(self, serializer): serializer.save(user=self.request.user) @action(detail=True, permission_classes=[permissions.IsAuthenticated]) def like(self, request, pk=None): obj, created = Like.objects.get_or_create(user=request.user, post=self.get_object()) if created: return Response({'data': ['Like successfully']}) else: return Response({'errors': ['You already like that post']}, status=status.HTTP_400_BAD_REQUEST) @action(detail=True, permission_classes=[permissions.IsAuthenticated]) def unlike(self, request, pk=None): if not Like.objects.filter(user=request.user, voice=self.get_object()).exists(): return Response({'errors': {"You aren't like that post"}}, status=status.HTTP_400_BAD_REQUEST) Like.objects.get(user=request.user, post=self.get_object()).delete() return Response({'data': ['Unlike successfully']})
urls.pyにも付け加えておきましょう。
router.register('posts', PostViewSet)
Djangoでいいね機能を作った時と基本的には変わらない感じかなー、と思います。
Nuxt側の実装
Nuxt側でいいね機能を実装してみましょう。Componentに分割したり、FontAwesomeとか使っているんですが、あんま気にしないでください(笑)。適時、読み替えてください。
PostのレイアウトやPost APIを受け取るところは省略させてください。今回はいいね機能の受け渡し、ということで。
<action-icon v-if="post.is_liking" slot="icon" icon="heart" :num="post.likes_count" @click.native="unlike"/> <action-icon v-else slot="icon" icon="heart" :num="post.likes_count" @click.native="like"/>
さて、scriptの方も書いていきましょう。
props: { post: { required: true } }, methods: { async like() { await this.$axios.get(`/api/posts/${this.post.id}/like/`) this.post.is_liking = true this.post.likes_count++ }, async unlike() { await this.$axios.get(`/api/posts/${this.post.id}/unlike/`) this.post.is_liking = false this.post.likes_count-- } }
ログインしておけばこれで色々動くと思います。いいね機能付け加えたい時、参考にしてください。PostのAPIの受け渡しに関してはおそらく色々と記事があるのでそれを参考にしてみてください。
何かあれば、じぇい👨💻 (@jyouj__) | Twitterに!