165 feat: add comments and quiz ratings#180
Conversation
Antoni-Czaplicki
left a comment
There was a problem hiding this comment.
some suggestions and also pls fix merge conflicts
| content = models.TextField() | ||
|
|
||
| # comment can be reply to other comment | ||
| parent = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name="replies") |
There was a problem hiding this comment.
EDIT: i see it's already done, however lets only mark it as deleted and don't remove content. also we could add last eddited_at field
prev. why not set ie is_deleted and don't return content for deleted in serializer? this would help us with potential moderation and prevent from one comment deletion removing the whole chain
| related_name="comments", # quiz.comments.all() | ||
| ) | ||
|
|
||
| # additionally, comment can be linked to question inside SharedQuiz |
There was a problem hiding this comment.
a little to much comments, i think we can remove them in places where the code makes everything clear
| "id", | ||
| "author", | ||
| "content", | ||
| "parent", |
There was a problem hiding this comment.
parent also neeeds to be validated if it belongs to a quiz
There was a problem hiding this comment.
and also check if user has access to quiz
| class QuizRatingViewSet(viewsets.ModelViewSet): | ||
| """ | ||
| Manages quiz ratings for the authenticated user. | ||
|
|
||
| All operations are scoped to the authenticated user. | ||
| A user can only have one rating per quiz (enforced by unique constraint). | ||
| """ | ||
|
|
||
| permission_classes = [permissions.IsAuthenticated] | ||
| serializer_class = QuizRatingSerializer | ||
| queryset = QuizRating.objects.all() | ||
|
|
||
| def get_queryset(self): | ||
| return QuizRating.objects.filter(user=self.request.user) | ||
|
|
||
|
|
||
| class CommentViewSet(viewsets.ModelViewSet): | ||
| """ | ||
| Manages comments for the authenticated user. | ||
|
|
||
| Access Control (get_queryset): | ||
| Users can only access comments if: | ||
| 1. They are the quiz maintainer (owner). | ||
| 2. The quiz has been shared with them directly or via their study groups. | ||
| 3. The quiz visibility is set to Public (visibility=3). | ||
|
|
||
| DELETE performs a soft delete — comment content is cleared but record is kept. | ||
| Only the author can modify or delete their own comments. | ||
| """ | ||
|
|
||
| permission_classes = [permissions.IsAuthenticated, IsCommentAuthorOrReadOnly] | ||
| serializer_class = CommentSerializer | ||
| queryset = Comment.objects.all() | ||
|
|
||
| def get_queryset(self): | ||
| user = self.request.user | ||
|
|
||
| shared_quiz_ids = SharedQuiz.objects.filter( | ||
| Q(user=user) | Q(study_group__in=user.study_groups.all()), quiz__visibility__gte=1 | ||
| ).values_list("quiz_id", flat=True) | ||
|
|
||
| return Comment.objects.filter( | ||
| Q(quiz__maintainer=user) # user is maintainer | ||
| | Q(quiz_id__in=shared_quiz_ids) # quiz was shared to user | ||
| | Q(quiz__visibility=3) # quiz is public | ||
| ) | ||
|
|
||
| def perform_destroy(self, instance: Comment): | ||
| if instance.is_deleted: | ||
| raise ValidationError("Comment is already deleted.") | ||
|
|
||
| instance.mark_as_deleted() |
There was a problem hiding this comment.
Okay, soooo
in general this probably should be a little more advanced - now it gives us an object without filters and anything.
we should:
- require quiz id to be provided to avoid returning a list of all users and public comments or reviews at once
- return quiz rating in quiz metadata serializer directly with average and review count
- only allow access to objects linked to users that have access to specific quiz
Opis
PR dodaje funkcjonalność komentarzy oraz oceniania quizów.
Zmiany
Modele
Commentz obsługą zagnieżdżonych odpowiedzi, soft delete oraz przypisaniem doSharedQuizlubQuestion(wymuszone przezCheckConstraint)QuizRating(1–5 gwiazdek) z unikalną oceną per użytkownik/quizget_average_rating()do modeluQuizSerializery
CommentSerializerz walidacją treści, obsługą soft delete oraz właściwościąis_replyQuizRatingSerializerzHiddenFielddla użytkownikaWidoki
CommentViewSet— pełny CRUD, soft delete przyDELETE, modyfikacja tylko przez autora viaIsCommentAuthorOrReadOnlyQuizRatingViewSet— pełny CRUD ograniczony do zalogowanego użytkownikaTesty
Uwagi