From 05cd9e8c7ea673272a6eb981accb726fb37f806a Mon Sep 17 00:00:00 2001 From: oguzpancuk <44545164+oguzpancuk@users.noreply.github.com> Date: Sun, 8 Dec 2024 23:47:27 +0300 Subject: [PATCH 1/2] Implemented follow and unfollow endpoints Initial commit --- backend/onboarding/serializers.py | 13 +++++++++++ backend/onboarding/views.py | 36 ++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/backend/onboarding/serializers.py b/backend/onboarding/serializers.py index c8b0f33e..432f0519 100644 --- a/backend/onboarding/serializers.py +++ b/backend/onboarding/serializers.py @@ -1,3 +1,4 @@ +from django.contrib.auth import get_user_model from onboarding.models import * from rest_framework import serializers from rest_framework_simplejwt.serializers import TokenObtainPairSerializer @@ -109,3 +110,15 @@ def update(self, instance, validated_data): instance.following.set(following) return super().update(instance, validated_data) + +User = get_user_model() +class FollowUnfollowSerializer(serializers.Serializer): + username = serializers.CharField() + + def validate_username(self, value): + # Ensure the username exists in the database + try: + user = User.objects.get(username=value) + except User.DoesNotExist: + raise serializers.ValidationError(f"User with username '{value}' does not exist.") + return value \ No newline at end of file diff --git a/backend/onboarding/views.py b/backend/onboarding/views.py index fe9d6114..d2f3e2ee 100644 --- a/backend/onboarding/views.py +++ b/backend/onboarding/views.py @@ -3,9 +3,11 @@ from django.contrib.sites.shortcuts import get_current_site from django.urls import reverse from django.template import Template, Context +from django.shortcuts import get_object_or_404 from django.conf import settings from django.http.response import JsonResponse from onboarding.models import User as User +from onboarding.models import Profile from rest_framework import permissions, status , viewsets, generics from rest_framework.response import Response from rest_framework_simplejwt.tokens import RefreshToken @@ -199,4 +201,36 @@ def update(self, request, pk=None): def destroy(self, request, pk=None): currency = self.get_object() currency.delete() - return Response(status=status.HTTP_204_NO_CONTENT) \ No newline at end of file + return Response(status=status.HTTP_204_NO_CONTENT) + + @action(detail=False, methods=['post'], url_path='follow') + def follow(self, request): + serializer = FollowUnfollowSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + username = serializer.validated_data['username'] + + user_to_follow = get_object_or_404(User, username=username) + profile_to_follow = user_to_follow.profile + user_profile = request.user.profile + + if user_profile in profile_to_follow.followers.all(): + return Response({'detail': 'Already following this user.'}, status=status.HTTP_400_BAD_REQUEST) + + profile_to_follow.followers.add(user_profile) + return Response({'detail': f'Successfully followed {username}.'}, status=status.HTTP_200_OK) + + @action(detail=False, methods=['post'], url_path='unfollow') + def unfollow(self, request): + serializer = FollowUnfollowSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + username = serializer.validated_data['username'] + + user_to_unfollow = get_object_or_404(User, username=username) + profile_to_unfollow = user_to_unfollow.profile + user_profile = request.user.profile + + if user_profile not in profile_to_unfollow.followers.all(): + return Response({'detail': 'You are not following this user.'}, status=status.HTTP_400_BAD_REQUEST) + + profile_to_unfollow.followers.remove(user_profile) + return Response({'detail': f'Successfully unfollowed {username}.'}, status=status.HTTP_200_OK) \ No newline at end of file From 542c00ccc7f5a7946683b0ef0c73c878a5dc770e Mon Sep 17 00:00:00 2001 From: oguzpancuk <44545164+oguzpancuk@users.noreply.github.com> Date: Mon, 9 Dec 2024 00:17:28 +0300 Subject: [PATCH 2/2] Created separate views for follow and unfollow Follow and unfollow now has their own views. --- backend/onboarding/urls.py | 2 ++ backend/onboarding/views.py | 22 ++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/backend/onboarding/urls.py b/backend/onboarding/urls.py index f722f0a6..76474400 100644 --- a/backend/onboarding/urls.py +++ b/backend/onboarding/urls.py @@ -20,5 +20,7 @@ path('register/', RegisterView.as_view(), name='auth_register'), path('email-verify/', VerifyEmail.as_view(), name='email-verify'), path('logout/', LogoutView.as_view(), name='logout'), + path('follow/', FollowView.as_view(), name='follow'), + path('unfollow/', UnfollowView.as_view(), name='unfollow'), path('', include(router.urls)), ] \ No newline at end of file diff --git a/backend/onboarding/views.py b/backend/onboarding/views.py index d2f3e2ee..a5cc6026 100644 --- a/backend/onboarding/views.py +++ b/backend/onboarding/views.py @@ -1,3 +1,4 @@ +from django.contrib.auth import get_user_model from django.shortcuts import render, redirect from django.views.decorators.csrf import csrf_exempt from django.contrib.sites.shortcuts import get_current_site @@ -203,9 +204,14 @@ def destroy(self, request, pk=None): currency.delete() return Response(status=status.HTTP_204_NO_CONTENT) - @action(detail=False, methods=['post'], url_path='follow') - def follow(self, request): - serializer = FollowUnfollowSerializer(data=request.data) +User = get_user_model() + +class FollowView(generics.GenericAPIView): + serializer_class = FollowUnfollowSerializer + permission_classes = [IsAuthenticated] + + def post(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) username = serializer.validated_data['username'] @@ -219,9 +225,13 @@ def follow(self, request): profile_to_follow.followers.add(user_profile) return Response({'detail': f'Successfully followed {username}.'}, status=status.HTTP_200_OK) - @action(detail=False, methods=['post'], url_path='unfollow') - def unfollow(self, request): - serializer = FollowUnfollowSerializer(data=request.data) + +class UnfollowView(generics.GenericAPIView): + serializer_class = FollowUnfollowSerializer + permission_classes = [IsAuthenticated] + + def post(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) username = serializer.validated_data['username']