Django-Rest-Frameworkでフォロー機能を作りたい


Django-Rest-Frameworkでフォロー機能を実装したいと思います。

フォロー機能を実装したい(api)

SNSサイトによくあるフォロー機能の実装するための手順

models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
    user_id = models.AutoField(primary_key=True, verbose_name="ユーザーID")
    username = models.CharField(max_length=20, verbose_name='ユーザー名', unique=True)
    email = models.EmailField('メールアドレス')
    prof_img = models.ImageField(upload_to='user/', verbose_name='プロフィール画像', null=True, blank=True, default='user/default.png')
    intro = models.TextField(verbose_name='自己紹介', max_length=300, null=True, blank=True)
    univ_name = models.CharField(verbose_name='大学名', max_length=30)
    major = models.CharField(verbose_name='学部・学科・専攻', max_length=50, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

class UserFollowing(models.Model):
    relation_id = models.AutoField(primary_key=True, verbose_name="関係ID")
    # フォローした人のid
    user_id = models.ForeignKey(CustomUser, related_name="following", on_delete=models.CASCADE)
    # フォローされた人のid
    following_user_id = models.ForeignKey(CustomUser, related_name="followers", on_delete=models.CASCADE)
    # フォローした日時を表示
    created = models.DateTimeField(auto_now_add=True)

一応CustomUserも載せておきますそこはなんでもいいです。
大事なのはその次のUserFollowingのクラスで、これはCustomUserとは別で作成します。

serializers.py
class FollowingSerializer(serializers.ModelSerializer):

    class Meta:
        model = UserFollowing
        fields = ("relation_id", "following_user_id", "created")

class FollowersSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserFollowing
        fields = ("relation_id", "user_id", "created")

class UserSerializer(serializers.ModelSerializer):
    following = serializers.SerializerMethodField()
    followers = serializers.SerializerMethodField()

    class Meta:
        model = CustomUser
        fields = ('user_id', 'username', 'email', 'prof_img', 'intro', 'univ_name',
                'major', 'following', "followers",)

    def get_following(self, obj):
        return FollowingSerializer(obj.following.all(), many=True).data

    def get_followers(self, obj):
        return FollowersSerializer(obj.followers.all(), many=True).data

シリアライザについて、フォローとフォロワーは別々でシリアライザは作成します。

で、それだけではなくUserSerializerについても少し工夫を加える必要があります。

serializers.SerializerMethodField()ってなに?

結論から言うとシリアライザのフィールドの値を動的に決めるための関数です。

UserSerializerを見てみると、modelにはなかった'following'と'followers'があることがわかります。

この値を決めるためにこのメソッドを定義します。

値の決め方については、その下にある、get_{フィールド名}関数を用います。この関数の返り値がそれぞれのフィールドに入ります。

views.py
class UserFollowingViewSet(viewsets.ModelViewSet):
    permission_classes = (IsAuthenticatedOrReadOnly,)
    serializer_class = FollowingSerializer
    queryset = UserFollowing.objects.all()

これで一応apiは完成です。