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, что является ожидаемым поведением. Если комментарий существует, он будет возвращен и использован для представления.