From 85eaa296355b27e014e584ae9320d061295fe67c Mon Sep 17 00:00:00 2001 From: kaan Date: Sat, 23 Nov 2024 20:18:01 +0300 Subject: [PATCH 1/2] added like count and modified is liked and is bookmarked --- ..._post_bookmarked_by_alter_bookmark_post.py | 26 ++++++++++++++ backend/app/models.py | 11 +++--- backend/app/serializers.py | 17 +++++++-- backend/app/views_directory/bookmark_views.py | 35 +++++++++++++++---- backend/app/views_directory/postviews.py | 4 +-- backend/app/views_directory/profileviews.py | 8 +++-- 6 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 backend/app/migrations/0002_post_bookmarked_by_alter_bookmark_post.py diff --git a/backend/app/migrations/0002_post_bookmarked_by_alter_bookmark_post.py b/backend/app/migrations/0002_post_bookmarked_by_alter_bookmark_post.py new file mode 100644 index 00000000..66248f17 --- /dev/null +++ b/backend/app/migrations/0002_post_bookmarked_by_alter_bookmark_post.py @@ -0,0 +1,26 @@ +# Generated by Django 4.2.16 on 2024-11-23 17:08 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('app', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='post', + name='bookmarked_by', + field=models.ManyToManyField(blank=True, related_name='bookmarked_posts', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='bookmark', + name='post', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.post'), + ), + ] diff --git a/backend/app/models.py b/backend/app/models.py index 3f85a9fe..179845ad 100644 --- a/backend/app/models.py +++ b/backend/app/models.py @@ -126,12 +126,12 @@ class Post(models.Model): created_at = models.DateTimeField(default=timezone.now) author = models.CharField(max_length=100) like_count = models.IntegerField(default=0) - liked_by = models.ManyToManyField(User, related_name='liked_posts', blank=True) + bookmarked_by = models.ManyToManyField(User, related_name='bookmarked_posts', blank=True) # Manages bookmarks + liked_by = models.ManyToManyField(User, related_name='liked_posts', blank=True) def __str__(self): return self.title - class Word(models.Model): word = models.CharField(max_length=255, unique=True) language = models.CharField(max_length=3, default='eng') # e.g., 'eng' for English @@ -179,15 +179,16 @@ class Comment(models.Model): def __str__(self): return f'Comment by {self.author.username} on {self.post}' + class Bookmark(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='bookmarks') - post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='bookmarked_by') + post = models.ForeignKey(Post, on_delete=models.CASCADE) # No related_name needed here created_at = models.DateTimeField(auto_now_add=True) class Meta: - unique_together = ('user', 'post') - ordering = ['-created_at'] + unique_together = ('user', 'post') # Ensure one bookmark per user per post + ordering = ['-created_at'] # Latest bookmarks first def __str__(self): return f"{self.user.username} bookmarked {self.post.title}" \ No newline at end of file diff --git a/backend/app/serializers.py b/backend/app/serializers.py index 00114552..18dd5243 100644 --- a/backend/app/serializers.py +++ b/backend/app/serializers.py @@ -5,15 +5,19 @@ class ProfileSerializer(serializers.ModelSerializer): - username = serializers.CharField(source='user.username', read_only=True) + username = serializers.CharField(source='user.username', read_only=True) posts = serializers.SerializerMethodField() comments = serializers.SerializerMethodField() follower_count = serializers.SerializerMethodField() following_count = serializers.SerializerMethodField() + is_followed = serializers.SerializerMethodField() class Meta: model = Profile - fields = ['username','name', 'level', 'posts', 'comments', 'follower_count', 'following_count'] + fields = [ + 'username', 'name', 'level', 'posts', 'comments', + 'follower_count', 'following_count', 'is_followed' + ] def get_posts(self, obj): """Get posts created by the user.""" @@ -33,6 +37,15 @@ def get_following_count(self, obj): """Get the count of following.""" return obj.following.count() + def get_is_followed(self, obj): + """Check if the authenticated user follows this profile.""" + request = self.context.get('request') + if not request or not request.user.is_authenticated: + return False + return obj.followers.filter(id=request.user.id).exists() + + + class UserSerializer(serializers.ModelSerializer): diff --git a/backend/app/views_directory/bookmark_views.py b/backend/app/views_directory/bookmark_views.py index 7f005847..454c7e58 100644 --- a/backend/app/views_directory/bookmark_views.py +++ b/backend/app/views_directory/bookmark_views.py @@ -11,9 +11,9 @@ @api_view(['POST']) @permission_classes([IsAuthenticated]) def bookmark_post(request): - post_id = request.data.get('post_id') + post_id = request.data.get("post_id") if not post_id: - return Response({"detail": "post_id is required."}, status=status.HTTP_400_BAD_REQUEST) + return Response({"detail": "Post ID is required."}, status=status.HTTP_400_BAD_REQUEST) post = get_object_or_404(Post, id=post_id) @@ -22,15 +22,27 @@ def bookmark_post(request): Bookmark.objects.create(user=request.user, post=post) - return Response({"detail": "Post bookmarked successfully."}, status=status.HTTP_201_CREATED) + # Include like and bookmark status in the response + is_liked = post.liked_by.filter(id=request.user.id).exists() + is_bookmarked = Bookmark.objects.filter(user=request.user, post=post).exists() + + return Response( + { + "detail": "Post bookmarked successfully.", + "is_liked": is_liked, + "is_bookmarked": is_bookmarked, + "like_count": post.like_count, + }, + status=status.HTTP_201_CREATED + ) @api_view(['POST']) @permission_classes([IsAuthenticated]) def unbookmark_post(request): - post_id = request.data.get('post_id') + post_id = request.data.get("post_id") if not post_id: - return Response({"detail": "post_id is required."}, status=status.HTTP_400_BAD_REQUEST) + return Response({"detail": "Post ID is required."}, status=status.HTTP_400_BAD_REQUEST) post = get_object_or_404(Post, id=post_id) @@ -40,8 +52,19 @@ def unbookmark_post(request): bookmark.delete() - return Response({"detail": "Post unbookmarked successfully."}, status=status.HTTP_200_OK) + # Include like and bookmark status in the response + is_liked = post.liked_by.filter(id=request.user.id).exists() + is_bookmarked = Bookmark.objects.filter(user=request.user, post=post).exists() + return Response( + { + "detail": "Post unbookmarked successfully.", + "is_liked": is_liked, + "is_bookmarked": is_bookmarked, + "like_count": post.like_count, + }, + status=status.HTTP_200_OK + ) @api_view(['POST']) @permission_classes([IsAuthenticated]) diff --git a/backend/app/views_directory/postviews.py b/backend/app/views_directory/postviews.py index 7ce1c514..90ddbacf 100644 --- a/backend/app/views_directory/postviews.py +++ b/backend/app/views_directory/postviews.py @@ -30,7 +30,7 @@ def like_post(request): ) # Include like and bookmark status in the response - is_liked = request.user in post.liked_by.all() + is_liked = post.liked_by.filter(id=request.user.id).exists() is_bookmarked = post.bookmarked_by.filter(id=request.user.id).exists() return Response( @@ -59,7 +59,7 @@ def unlike_post(request): post.save() # Include like and bookmark status in the response - is_liked = request.user in post.liked_by.all() + is_liked = post.liked_by.filter(id=request.user.id).exists() is_bookmarked = post.bookmarked_by.filter(id=request.user.id).exists() return Response( diff --git a/backend/app/views_directory/profileviews.py b/backend/app/views_directory/profileviews.py index e956dfe7..b2f069e7 100644 --- a/backend/app/views_directory/profileviews.py +++ b/backend/app/views_directory/profileviews.py @@ -8,15 +8,16 @@ from app.models import Profile -@api_view(['POST']) +@api_view(['GET']) @permission_classes([IsAuthenticated]) def view_profile(request): user = request.user profile = get_object_or_404(Profile, user=user) - serializer = ProfileSerializer(profile) + serializer = ProfileSerializer(profile, context={'request': request}) return Response(serializer.data, status=status.HTTP_200_OK) + @api_view(['POST']) @permission_classes([IsAuthenticated]) def update_profile(request): @@ -37,7 +38,8 @@ def view_other_profile(request, username): """ user = get_object_or_404(User, username=username) profile = get_object_or_404(Profile, user=user) - serializer = ProfileSerializer(profile) + serializer = ProfileSerializer(profile, context={'request': request}) return Response(serializer.data, status=status.HTTP_200_OK) + From 4a97bfeaf1226f5e6dbe25b583fcd078c6b699af Mon Sep 17 00:00:00 2001 From: kaan Date: Sat, 23 Nov 2024 20:38:29 +0300 Subject: [PATCH 2/2] tested --- backend/app/views_directory/follow_unfollow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/app/views_directory/follow_unfollow.py b/backend/app/views_directory/follow_unfollow.py index 29840ec5..754c78dc 100644 --- a/backend/app/views_directory/follow_unfollow.py +++ b/backend/app/views_directory/follow_unfollow.py @@ -14,12 +14,12 @@ def follow_user(request): if user_to_follow != current_user_profile: current_user_profile.following.add(user_to_follow) + # Updated ActivityStream creation without 'target' ActivityStream.objects.create( actor=request.user, verb="followed", object_type="Profile", - object_id=user_to_follow.user.id, - target=None # Optional: could be used for specific contexts + object_id=user_to_follow.user.id ) return JsonResponse({"message": "Followed successfully"}, status=200)