Django 404 Использование функции get_queryset()

Это часть моего файла views.py

class CommentDetail(generics.RetrieveUpdateDestroyAPIView):
    def get_queryset(self):
        event_id = self.kwargs['pk']
        comment_id = self.kwargs['comment_pk']
        event = Event.objects.get(id=event_id)
        queryset = Comment.objects.filter(event=event, id=comment_id)
        return queryset
    
    serializer_class = CommentSerializer

Это url:

path('<int:pk>/comments/<int:comment_pk>/', views.CommentDetail.as_view(), name='comment-detail'),

Это модель:

class Comment(models.Model):
    event = models.ForeignKey(Event, on_delete=models.CASCADE , related_name='comments_for_event')
    author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    content = models.TextField(max_length=200)
    timestamp = models.DateTimeField(auto_now_add=True)
    
    def __str__(self):
        return f'{self.author} on {self.event.title} : {self.content}'

По какой-то причине я получаю ответ 404 с этой конечной точкой: http://127.0.0.1:8000/groups/2/messages/3/

Я попытался добавить операторы печати следующим образом:

class CommentDetail(generics.RetrieveUpdateDestroyAPIView):
    def get_queryset(self):
        event_id = self.kwargs['pk']
        comment_id = self.kwargs['comment_pk']
        print('Event ID:', event_id)
        print('Comment ID:', comment_id)
        event = Event.objects.get(id=event_id)
        queryset = Comment.objects.filter(event=event, id=comment_id)
        print('Queryset:', queryset)
        return queryset
    
    serializer_class = CommentSerializer

И я получаю такой вывод:

Event ID: 24
Comment ID: 2
Queryset: <QuerySet [<Comment: myuser on First event : It was amazing !!>]>
Not Found: /events/24/comments/2/

что означает, что запрос находит нужный объект, но что-то все равно не так, потому что я получаю 404:

HTTP 404 Not Found
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "detail": "No Comment matches the given query."
}

Проблема, с которой вы столкнулись, скорее всего, связана с тем, как работают общие представления Django REST Framework. В вашем представлении CommentDetail вы переопределяете метод get_queryset, чтобы вернуть набор запросов, который фильтруется по событию и id. Однако функция RetrieveUpdateDestroyAPIView в Django REST Framework ожидает, что кверисет, возвращаемый get_queryset, будет содержать все возможные объекты, которые могут быть просмотрены этим представлением. Затем он применяет собственную фильтрацию для поиска конкретного объекта на основе URL kwargs.

В вашем случае метод get_queryset возвращает кверисет, содержащий только интересующий вас комментарий. Когда Django REST Framework применяет свою собственную фильтрацию, он не находит комментарий в кверисете (потому что он ищет комментарий с pk=comment_pk, а ваш кверисет содержит комментарии с pk=event_id), и поэтому он возвращает 404.

Чтобы исправить это, вам следует обновить метод get_queryset, чтобы он возвращал все возможные комментарии, и переопределить метод get_object, чтобы найти конкретный комментарий:

from django.shortcuts import get_object_or_404


class CommentDetail(generics.RetrieveUpdateDestroyAPIView):
    def get_queryset(self):
        return Comment.objects.all()

    def get_object(self):
        event_id = self.kwargs['pk']
        comment_id = self.kwargs['comment_pk']
        event = Event.objects.get(id=event_id)
        return get_object_or_404(Comment, event=event, id=comment_id)

    serializer_class = CommentSerializer

В этом коде get_queryset возвращает все комментарии, а get_object использует функцию Django get_object_or_404 для поиска конкретного комментария на основе события и id. Это должно устранить ошибку 404, которую вы видите. Если комментарий не существует, get_object_or_404 выдаст ошибку 404, что является ожидаемым поведением. Если комментарий существует, он будет возвращен и использован для представления.

Вернуться на верх