I created a follow and unfollow system similar to Instagram.
Functionality:
- If private account enable --> send follow request.
- If user in block list --> they can not follow of opposite user.
- User can check pending request, sended request list,blocked user
list,etc.
Let's start :
Models.py:
class Profile(models.Model):
user = models.OneToOneField(to = User,on_delete=models.CASCADE,related_name='profile')
.......
private_account = models.BooleanField(default = False)
followers = models.ManyToManyField('self',blank=True,related_name='user_followers',symmetrical=False)
following = models.ManyToManyField('self',blank=True,related_name='user_following',symmetrical=False)
panding_request = models.ManyToManyField('self',blank=True,related_name='pandingRequest',symmetrical=False)
blocked_user = models.ManyToManyField('self',blank=True,related_name='user_blocked',symmetrical=False)
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s' %(self.user)
- Here you can follow, unfollow, send follow request, accept follow request,
decline request and you can remove your follower.
- From the front end side pass opposite user profile id and type
of action(follow,unfollow..).
views.py:
class FollowUnfollowView(APIView):
permission_classes = [IsAuthenticated]
def current_profile(self):
try:
return Profile.objects.get(user = self.request.user)
except Profile.DoesNotExist:
raise Http404
def other_profile(self,pk):
try:
return Profile.objects.get(id = pk)
except Profile.DoesNotExist:
raise Http404
def post(self, request,format=None):
pk = request.data.get('id') # Here pk is opposite user's profile ID
req_type = request.data.get('type')
current_profile = self.current_profile()
other_profile = self.other_profile(pk)
if req_type == 'follow':
if other_profile.private_account:
other_profile.panding_request.add(current_profile)
return Response({"Requested" : "Follow request has been send!!"},status=status.HTTP_200_OK)
else:
if other_profile.blocked_user.filter(id = current_profile.id).exists():
return Response({"Following Fail" : "You can not follow this profile becuase your ID blocked by this user!!"},status=status.HTTP_400_BAD_REQUEST)
current_profile.following.add(other_profile)
other_profile.followers.add(current_profile)
return Response({"Following" : "Following success!!"},status=status.HTTP_200_OK)
elif req_type == 'accept':
current_profile.followers.add(other_profile)
other_profile.following.add(current_profile)
current_profile.panding_request.remove(other_profile)
return Response({"Accepted" : "Follow request successfuly accespted!!"},status=status.HTTP_200_OK)
elif req_type == 'decline':
current_profile.panding_request.remove(other_profile)
return Response({"Decline" : "Follow request successfully declined!!"},status=status.HTTP_200_OK)
elif req_type == 'unfollow':
current_profile.following.remove(other_profile)
other_profile.followers.remove(current_profile)
return Response({"Unfollow" : "Unfollow success!!"},status=status.HTTP_200_OK)
elif req_type == 'remove': # You can remove your follower
current_profile.followers.remove(other_profile)
other_profile.following.remove(current_profile)
return Response({"Remove Success" : "Successfuly removed your follower!!"},status=status.HTTP_200_OK)
# Here we can fetch followers,following detail and blocked user,pending request,sended request..
def patch(self, request,format=None):
req_type = request.data.get('type')
if req_type == 'follow_detail':
serializer = FollowerSerializer(self.current_profile())
return Response({"data" : serializer.data},status=status.HTTP_200_OK)
elif req_type == 'block_pending':
serializer = BlockPendinSerializer(self.current_profile())
pf = list(Profile.objects.filter(panding_request = self.current_profile().id).values('id','user__username','profile_pic','overall_pr'))
return Response({"data" : serializer.data,"Sended Request" :pf},status=status.HTTP_200_OK)
# You can block and unblock user
def put(self, request,format=None):
pk = request.data.get('id') # Here pk is oppisite user's profile ID
req_type = request.data.get('type')
if req_type == 'block':
self.current_profile().blocked_user.add(self.other_profile(pk))
return Response({"Blocked" : "This user blocked successfuly"},status=status.HTTP_200_OK)
elif req_type == 'unblock':
self.current_profile().blocked_user.remove(self.other_profile(pk))
return Response({"Unblocked" : "This user unblocked successfuly"},status=status.HTTP_200_OK)
serializers.py:
class EachUserSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username')
class Meta:
model = Profile
fields = ('id','username','profile_pic')
read_only_fields = ('id','username','profile_pic')
class FollowerSerializer(serializers.ModelSerializer):
followers = EachUserSerializer(many=True, read_only= True)
following = EachUserSerializer(many=True,read_only=True)
class Meta:
model = Profile
fields = ('followers','following')
read_only_fields = ('followers','following')
class BlockPendinSerializer(serializers.ModelSerializer):
panding_request = EachUserSerializer(many=True, read_only= True)
blocked_user = EachUserSerializer(many=True,read_only=True)
class Meta:
model = Profile
fields = ('panding_request','blocked_user')
read_only_fields = ('panding_request','blocked_user')
urls.py:
from django.urls.conf import path
from .views import *
urlpatterns = [
.....
path('follow_unfollow/',FollowUnfollowView.as_view(),name = "follow_unfollow"),
]
If any doubt of any step please comment. I will briefly describe.