I am new to Djnago and I am designing my first Social Media App, so I am a bit new to this.
I have an API view to get a users profile and their posts. I have implemented logic to check if the requesting user is able to view another users posts based on their profile_privacy and if the requesting user follows them or not.
If the requesting user is able to view the users posts, then and only then we query for their posts.
My question is: Since the posts are paginated, when the user requests for the profile, it will perform the logic and then get the appropriate posts, however, when we query for the second page of Post data, it will perform the same logic and checks again (check the follow instance to see if the requesting user follows them). Instead of performing this logic for every page query, is there a way to check it only once since for all other page requests we know the user already follows them?
One approach was checking if the page being requested is the first page and only perform the checks for that, but that introduces security issues since if a user who does not follow a private user queries the second page, it will skip the logic and show the posts.
Is my current implementation fine or can it be improved to be more efficient?
I hope I made the question clear.
This is the API view I made:
@permission_classes([IsAuthenticated])
def user_profile(request, user_id):
try:
user = User.objects.get(id=user_id)
except User.DoesNotExist:
return Response({"error": "User not found"}, status=status.HTTP_404_NOT_FOUND)
follow_status = False # Keeps track of the requesting user's follow relationship to the user they are viewing
can_view = True # Keeps track of whether the requesting user can view this user's profile or not
# Check if the user is attempting to view their own profile
if request.user.id == user_id:
follow_status = "self"
else:
follow_instance = request.user.following.filter(following=user).first()
if follow_instance:
follow_status = follow_instance.follow_status
if user.profile_privacy == 'private' and (follow_status is False or follow_status == 'pending'):
can_view = False
# Initialize the response_data dictionary
response_data = {
'username': user.username,
'profile_picture': user.profile_picture.url if user.profile_picture else None,
'bio': user.bio,
'follow_status': follow_status,
'can_view': can_view,
'num_followers': user.num_followers,
'num_following': user.num_following,
'num_posts': user.num_posts,
'posts': None, # Initialize 'posts' as None
}
if can_view:
# Create an instance of custom LargePagination class
paginator = LargePagination()
# Paginate the queryset of the user's posts
users_posts = Post.objects.filter(user=user)
page = paginator.paginate_queryset(users_posts, request)
serializer = PostSerializer(page, many=True, context={'request': request})
# Update the 'posts' field in response_data with serialized data
response_data['posts'] = serializer.data
return Response(response_data, status=status.HTTP_200_OK)