Skip to content

Commit e8476fa

Browse files
authoredMar 18, 2025
feat: work on profile page (#251)
1 parent ad5afbf commit e8476fa

37 files changed

+1153
-761
lines changed
 

‎backend/apps/api/serializers/comment/__init__.py

+64-9
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,74 @@
22
from rest_framework import serializers
33

44
from apps.comment.models import Comment
5+
from apps.post.models import Post
56

67
from ...serializers.user.profile import ProfileBasicSerializer
78

89

10+
class CommentSerializer(serializers.ModelSerializer):
11+
commenter = ProfileBasicSerializer(allow_null=True)
12+
ratio = serializers.IntegerField()
13+
14+
class Meta:
15+
model = Comment
16+
fields = '__all__'
17+
18+
19+
class CommentOverviewSerializer(CommentSerializer):
20+
commenter = serializers.SerializerMethodField()
21+
post = serializers.SerializerMethodField()
22+
reply_to = serializers.SerializerMethodField()
23+
is_op = serializers.SerializerMethodField()
24+
25+
class Meta(CommentSerializer.Meta):
26+
fields = (
27+
'id',
28+
'commenter',
29+
'reply_to',
30+
'is_op',
31+
'ratio',
32+
'post',
33+
'created_at',
34+
'content',
35+
'upvotes',
36+
'downvotes',
37+
)
38+
39+
def get_commenter(self, obj):
40+
return obj.commenter.username
41+
42+
def get_post(self, obj):
43+
request = self.context.get('request')
44+
45+
if post := Post.objects.filter(comments=obj).first():
46+
return {
47+
"id": post.pk,
48+
"title": post.title,
49+
"slug": post.slug,
50+
"community": {
51+
"name": post.community.name,
52+
"avatar": (
53+
request.build_absolute_uri(post.community.avatar.url)
54+
if post.community.avatar
55+
else None
56+
),
57+
},
58+
}
59+
return None
60+
61+
def get_reply_to(self, obj):
62+
if parent := obj.parent():
63+
return parent.commenter.username
64+
return None
65+
66+
def get_is_op(self, obj):
67+
post = Post.objects.filter(comments=obj).first()
68+
if post and post.poster == obj.commenter:
69+
return True
70+
return False
71+
72+
973
class CommentCreateSerializer(serializers.ModelSerializer):
1074
path = serializers.CharField(required=False)
1175

@@ -29,12 +93,3 @@ def create(self, validated_data):
2993

3094
comment_instance.upvotes.add(data['commenter'])
3195
return comment_instance
32-
33-
34-
class CommentDetailSerializer(serializers.ModelSerializer):
35-
commenter = ProfileBasicSerializer(allow_null=True)
36-
ratio = serializers.IntegerField()
37-
38-
class Meta:
39-
model = Comment
40-
fields = '__all__'

‎backend/apps/api/serializers/user/profile/downvoted.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22

33
from rest_framework import serializers
44

5-
from apps.api.serializers.comment import CommentDetailSerializer
5+
from apps.api.serializers.comment import CommentSerializer
66
from apps.api.serializers.post import PostSerializer
77

88

99
class DownvotedSerializer(serializers.Serializer):
1010
content_type = serializers.CharField()
11-
data = serializers.SerializerMethodField()
11+
content = serializers.SerializerMethodField()
1212

13-
def get_data(self, obj) -> dict:
13+
def get_content(self, obj) -> dict:
1414
obj_type = obj.content_type
1515
obj_copy = copy.copy(obj)
1616

1717
delattr(obj_copy, "content_type")
1818

1919
if obj_type == "post":
2020
return PostSerializer(obj_copy, context=self.context).data
21-
return CommentDetailSerializer(obj_copy, context=self.context).data
21+
return CommentSerializer(obj_copy, context=self.context).data

‎backend/apps/api/serializers/user/profile/overview.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22

33
from rest_framework import serializers
44

5-
from apps.api.serializers.comment import CommentDetailSerializer
5+
from apps.api.serializers.comment import CommentOverviewSerializer
66
from apps.api.serializers.post import PostSerializer
77

88

99
class OverviewSerializer(serializers.Serializer):
1010
content_type = serializers.CharField()
11-
data = serializers.SerializerMethodField()
11+
content = serializers.SerializerMethodField()
1212

13-
def get_data(self, obj) -> dict:
13+
def get_content(self, obj) -> dict:
1414
obj_type = obj.content_type
1515
obj_copy = copy.copy(obj)
1616

1717
delattr(obj_copy, "content_type")
1818

1919
if obj_type == "post":
2020
return PostSerializer(obj_copy, context=self.context).data
21-
return CommentDetailSerializer(obj_copy, context=self.context).data
21+
return CommentOverviewSerializer(obj_copy, context=self.context).data

‎backend/apps/api/serializers/user/profile/upvoted.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22

33
from rest_framework import serializers
44

5-
from apps.api.serializers.comment import CommentDetailSerializer
5+
from apps.api.serializers.comment import CommentSerializer
66
from apps.api.serializers.post import PostSerializer
77

88

99
class UpvotedSerializer(serializers.Serializer):
1010
content_type = serializers.CharField()
11-
data = serializers.SerializerMethodField()
11+
content = serializers.SerializerMethodField()
1212

13-
def get_data(self, obj) -> dict:
13+
def get_content(self, obj) -> dict:
1414
obj_type = obj.content_type
1515
obj_copy = copy.copy(obj)
1616

1717
delattr(obj_copy, "content_type")
1818

1919
if obj_type == "post":
2020
return PostSerializer(obj_copy, context=self.context).data
21-
return CommentDetailSerializer(obj_copy, context=self.context).data
21+
return CommentSerializer(obj_copy, context=self.context).data

‎backend/apps/api/viewsets/comment/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
from mixins.api.reaction import ReactionMixin
44

55
from ...bases.viewsets import UpdateRetrieveDestroyViewSet
6-
from ...serializers.comment import CommentDetailSerializer
6+
from ...serializers.comment import CommentSerializer
77

88

99
class CommentViewSet(ReactionMixin, UpdateRetrieveDestroyViewSet):
1010
queryset = Comment.objects.all()
11-
serializer_class = CommentDetailSerializer
11+
serializer_class = CommentSerializer
1212

1313
serializer_mapping = {
1414
'reaction': ReactionSerializer,

‎backend/apps/api/viewsets/community/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def get_object(self) -> Community: # pyright: ignore
4444

4545
if not obj:
4646
raise exceptions.NotFound(
47-
f'Community with name <b>{self.kwargs[self.lookup_field]}</b> not found.'
47+
f'Community with name <b>q/{self.kwargs[self.lookup_field]}</b> not found.'
4848
)
4949
return obj
5050

‎backend/apps/api/viewsets/post/__init__.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from apps.post.models import Post
1111
from mixins.api.reaction import ReactionMixin
1212

13-
from ...serializers.comment import CommentCreateSerializer, CommentDetailSerializer
13+
from ...serializers.comment import CommentCreateSerializer, CommentSerializer
1414
from ...serializers.post import PostCreateSerializer, PostSerializer
1515

1616

@@ -68,7 +68,7 @@ def create(self, request):
6868
response_serializer = PostSerializer(post_instance, context=context)
6969
return response.Response(response_serializer.data, status=status.HTTP_201_CREATED)
7070

71-
@extend_schema(responses=CommentDetailSerializer(many=True))
71+
@extend_schema(responses=CommentSerializer(many=True))
7272
@action(detail=True, methods=[HTTPMethod.GET, HTTPMethod.POST])
7373
def comments(self, request, pk=None):
7474
post_instance = get_object_or_404(Post, pk=pk)
@@ -77,7 +77,7 @@ def comments(self, request, pk=None):
7777

7878
if request.method == HTTPMethod.GET:
7979
comments = post_instance.comments.all() # pyright: ignore
80-
serializer = CommentDetailSerializer(comments, many=True, context=context)
80+
serializer = CommentSerializer(comments, many=True, context=context)
8181

8282
return response.Response(serializer.data, status=status.HTTP_200_OK)
8383

@@ -89,5 +89,5 @@ def comments(self, request, pk=None):
8989
# hard-code ratio
9090
comment_instance.ratio = 1
9191

92-
response_serializer = CommentDetailSerializer(comment_instance, context=context)
92+
response_serializer = CommentSerializer(comment_instance, context=context)
9393
return response.Response(response_serializer.data, status=status.HTTP_201_CREATED)

‎backend/apps/api/viewsets/user/__init__.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from rest_framework.decorators import action
99
from rest_framework.response import Response
1010

11-
from apps.api.serializers.comment import CommentDetailSerializer
11+
from apps.api.serializers.comment import CommentOverviewSerializer, CommentSerializer
1212
from apps.api.serializers.post import PostSerializer
1313
from apps.api.serializers.user.profile import (
1414
ProfileSerializer,
@@ -33,11 +33,12 @@ class ProfileViewSet(viewsets.ReadOnlyModelViewSet):
3333
serializer_class = ProfileSerializer
3434
filter_backends = (filters.SearchFilter,)
3535
search_fields = ("username",)
36+
lookup_field = 'username'
3637

3738
serializer_classes = {
3839
"overview": OverviewSerializer,
3940
"posts": PostSerializer,
40-
"comments": CommentDetailSerializer,
41+
"comments": CommentOverviewSerializer,
4142
"upvoted": UpvotedSerializer,
4243
"downvoted": DownvotedSerializer,
4344
}
@@ -63,7 +64,7 @@ def get_object(self) -> Profile:
6364

6465
@extend_schema(responses=OverviewSerializer(many=True))
6566
@action(detail=True, methods=[HTTPMethod.GET])
66-
def overview(self, request, pk=None):
67+
def overview(self, request, username=None):
6768
"""Returns a mixed list of posts and comments by the user, ordered by date."""
6869
profile = self.get_object()
6970
posts = profile.posts.all().annotate(content_type=Value("post", CharField()))
@@ -77,16 +78,16 @@ def overview(self, request, pk=None):
7778

7879
@extend_schema(responses=PostSerializer(many=True))
7980
@action(detail=True, methods=[HTTPMethod.GET])
80-
def posts(self, request, pk=None):
81+
def posts(self, request, username=None):
8182
"""Returns a list of posts by the user, ordered by date."""
8283
profile = self.get_object()
8384
posts = profile.posts.all().order_by("-created_at")
8485
serialized_data = self.get_serializer(posts, context={"request": request}, many=True).data
8586
return Response(serialized_data)
8687

87-
@extend_schema(responses=CommentDetailSerializer(many=True))
88+
@extend_schema(responses=CommentOverviewSerializer(many=True))
8889
@action(detail=True, methods=[HTTPMethod.GET])
89-
def comments(self, request, pk=None):
90+
def comments(self, request, username=None):
9091
"""Returns a list of comments by the user, ordered by date."""
9192
profile = self.get_object()
9293
comments = profile.comments.all().order_by("-created_at")
@@ -97,7 +98,7 @@ def comments(self, request, pk=None):
9798

9899
@extend_schema(responses=UpvotedSerializer(many=True))
99100
@action(detail=True, methods=[HTTPMethod.GET])
100-
def upvoted(self, request, pk=None):
101+
def upvoted(self, request, username=None):
101102
"""Returns a mixed list of upvoted posts and comments by the user, ordered by date."""
102103
profile = self.get_object()
103104
posts = profile.upvoted_posts.all().annotate(content_type=Value("post", CharField()))
@@ -113,7 +114,7 @@ def upvoted(self, request, pk=None):
113114

114115
@extend_schema(responses=DownvotedSerializer(many=True))
115116
@action(detail=True, methods=[HTTPMethod.GET])
116-
def downvoted(self, request, pk=None):
117+
def downvoted(self, request, username=None):
117118
"""Returns a mixed list of downvoted posts and comments by the user, ordered by date."""
118119
profile = self.get_object()
119120
posts = profile.downvoted_posts.all().annotate(content_type=Value("post", CharField()))

‎backend/apps/user/admin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class ProfileAdmin(admin.ModelAdmin):
4545
fieldsets = (
4646
(
4747
None,
48-
{'fields': ('user', 'username', 'name', 'avatar', 'banner')},
48+
{'fields': ('user', 'username', 'avatar', 'banner', 'name', 'bio')},
4949
),
5050
(_('important dates'), {'fields': ('created_at',)}),
5151
)

0 commit comments

Comments
 (0)