Optimizing Django Social Media App: Efficient Handling of Profile Privacy and Pagination Logic for Post Retrieval

25 views Asked by At

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)
0

There are 0 answers