DjangoでAPI&Nuxtでフォロー機能を実装
以前、Djangoでフォロー機能を実装したことがありましたが、今回はDjangoの方でAPIを用意してあげて、Nuxt.jsを使い、実装する方法を紹介します。
<過去記事>
jyouj.hatenablog.com
Djangoでフォロー関係のAPI
rest_framework関連のsettings.pyへの設定は詳しい記事がありますので、そちらをご覧ください。
Django REST Frameworkを使って爆速でAPIを実装する - Qiita
まずはserializers.pyを作成しておきましょう。すでにUserモデルはできていると仮定します。
from rest_framework import serializers from users.models import User class UserMiniSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('id', 'name', 'username', 'icon', 'about_me') class UserSerializer(serializers.ModelSerializer): followings_count = serializers.SerializerMethodField() followers_count = serializers.SerializerMethodField() is_following = serializers.SerializerMethodField() class Meta: model = User fields = ('id', 'username', 'name', 'icon', 'about_me', 'date_joined', 'updated_at', 'followings_count', 'followers_count', 'is_following') def get_followings_count(self, obj): return obj.get_followings().count() def get_followers_count(self, obj): return obj.get_followers().count() def get_is_following(self, obj): user = self.context['request'].user if user.is_authenticated: return obj in user.get_followings() else: return False
ログインしている時のみの動作に注意しておきます。
ここで、一つpermissionを作っておきます。
from rest_framework import permissions class IsMyselfOrReadOnly(permissions.BasePermission): def has_object_permission(self, request, view, obj): if request.method in permissions.SAFE_METHODS: return True return obj == request.user
次にviewsetを作っていきましょう。
from django.shortcuts import render from rest_framework import viewsets, filters, status, permissions from rest_framework.response import Response from rest_framework.decorators import action from users.models import User, Connection from .serializers import UserSerializer, UserMiniSerializer from .permissions import IsMyselfOrReadOnly class UserViewSet(viewsets.ReadOnlyModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsMyselfOrReadOnly] lookup_field = 'username' filter_backends = [filters.SearchFilter] search_fields = ['name', 'username', 'about_me'] @action(detail=True, permission_classes=[permissions.IsAuthenticated]) def follow(self, request, username=None): follower = request.user following = self.get_object() if follower == following: return Response({'errors': ['You cannot follow your account']}, status=status.HTTP_400_BAD_REQUEST) obj, created = Connection.objects.get_or_create(follower=follower, following=following) if (created): return Response({'data': ['Follow successfully']}) else: return Response({'errors': ['You already follow']}, status=status.HTTP_400_BAD_REQUEST) @action(detail=True, permission_classes=[permissions.IsAuthenticated]) def unfollow(self, request, username=None): follower = request.user following = self.get_object() if follower == following: return Response({'errors': ['You cannot unfollow your account']}, status=status.HTTP_400_BAD_REQUEST) if not Connection.objects.filter(follower=follower, following=following).exists(): return Response({'errors': {"You aren't following that account"}}, status=status.HTTP_400_BAD_REQUEST) Connection.objects.get(follower=follower, following=following).delete() return Response({'data': ['Unfollow successfully']}) @action(detail=True) def followings(self, request, username=None): users = self.get_object().get_followings() serializer = UserMiniSerializer(users, many=True, context={'request': request}) return Response(serializer.data) @action(detail=True) def followers(self, request, username=None): users = self.get_object().get_followers() serializer = UserMiniSerializer(users, many=True, context={'request': request}) return Response(serializer.data)
そして、urls.pyを作成し、DjangoでのAPIは完成です。
from django.urls import path, include from rest_framework.routers import DefaultRouter from apis.views import UserViewSet router = DefaultRouter() router.register('users', UserViewSet) urlpatterns = [ path('', include(router.urls)), ]
Nuxt側の実装
APIの受け渡しにはaxiosを使います。詳しくは下記をご覧ください。
それでは、フォロー機能を実装していきましょう。pages/_id/index.vueに書いておきましょう。
<template> <div> <b-button v-else-if="$auth.loggedIn && user.is_following" @click="unfollow()" variant="success">アンフォロー</b-button> <b-button v-else-if="$auth.loggedIn && !user.is_following" variant="success" @click="follow()">フォロー</b-button> </div> </template>
もちろんログインしていることが条件です。rest_authは今度記事にします。公式ドキュメントがわかりやすいので、読んでみてもいいかも知れないですね。
<script></script>の方には、
asyncData(context) { return context.$axios .$get(`/api/users/${context.params.id}/`) .then(res => { return { user: res } }) .catch(e => { context.error({ statusCode: 404 }) }) }, methods: { async follow() { await this.$axios.get(`/api/users/${this.user.username}/follow/`) this.user.is_following = true this.user.followers_count++ }, async unfollow() { await this.$axios.get(`/api/users/${this.user.username}/unfollow/`) this.user.is_following = false this.user.followers_count-- } }
認証関連をちゃんと作成できたら動くかな、と思います。
何かありましたら、じぇい👨💻 (@jyouj__) | Twitterに!
Nuxt.jsビギナーズガイドVue.js ベースのフレームワークによるシングルページアプリケーション開発【電子書籍】[ 花谷拓磨 ]
- ジャンル: 本・雑誌・コミック > PC・システム開発 > プログラミング > プログラミング入門
- ショップ: 楽天Kobo電子書籍ストア
- 価格: 3,324円