Django Rest Framework с shortuuid, generics.RetrieveUpdateDestroyAPIView возвращает 404 {"detail": "Не найдено."}

Я переделывал сайт социальной сети, дорабатывая Django и фреймворк rest, я не хотел использовать стандартный линейный подсчет id в django и мне не нравилось, насколько длинными были id в библиотеке uuid, поэтому я использовал библиотеку shortuuid. Я использовал их для постов и комментариев, просто чтобы сохранить анонимность подсчета как постов, так и комментариев. На стороне постов все работает для CRUD вещей (что должно быть доказательством того, что проблема не от библиотеки shortuuid, насколько я знаю), хотя с комментариями Create Retrieve работает отлично, но Update Destroy не работает. Итак, вот код, с которым мы работаем:

начинаем с моделей, чтобы знать, с какими данными мы работаем (models.py):

from shortuuid.django_fields import ShortUUIDField

... # posts likes etc


class Comment(models.Model):
    id = ShortUUIDField(primary_key=True, length=8, max_length=10)
    user    = models.ForeignKey(User, on_delete=models.CASCADE)
    post    = models.ForeignKey(Post, on_delete=models.CASCADE)
    body    = models.TextField(max_length=350)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    active  = models.BooleanField(default=True)

    class Meta:
        ordering = ['created']

    def __str__(self):
        return f'on {self.post} by {self.user}'

    objects = models.Manager()

serializers.py:

class CommentSerializer(ModelSerializer):
    username = SerializerMethodField()

    def get_username(self, comment):
        return str(comment.user)

    class Meta:
        model = Comment
        fields = ['id', 'user', 'post', 'username', 'body', 'created', 'updated']
        read_only_fields = ['id', 'post', 'user', 'username']

теперь с маршрутизацией (urls.py):

from django.urls import path
from .views import *


urlpatterns = [
    ...

    path('<str:pk>/comments/'       , Comments),
    path('<str:pk>/comments/create/', CreateComment),
    path('<str:pk>/comments/<str:cm>/', ModifyComment),
    # pk = post ID
    # cm = comment ID
]

views.py:

class ModifyComment(generics.RetrieveUpdateDestroyAPIView):
    serializer_class = CommentSerializer
    permission_classes = [permissions.AllowAny]

    def get_queryset(self):
        post = Post.objects.get(pk=self.kwargs['pk'])
        comment = Comment.objects.get(post=post, pk=self.kwargs['cm'])
        return comment


    def perform_update(self, serializer):
        print(Post.objects.all())
        post = Post.objects.get(pk=self.kwargs['pk'])
        comment = Comment.objects.filter(pk=self.kwargs['cm'], post=post)
        if self.request.user != comment.user:
            raise ValidationError('you can\'t edit another user\'s post')
        if comment.exists():
            serializer.save(user=self.request.user, comment=comment)
        else:
            raise ValidationError('the comment doesnt exist lol')

    def delete(self, request, *args, **kwargs):
        comment = Comment.objects.filter(user=self.request.user, pk=self.kwargs['cm'])
        if comment.exists():
            return self.destroy(request, *args, **kwargs)
        else:
            raise ValidationError("you can\'t delete another user\'s post")
ModifyComment = ModifyComment.as_view()

и в ответ на переход по url '<str:pk>/comments/<str:cm>/' комментария какого-то поста мы получаем следующее: example of the response

<

Для отдельных объектов необходимо переписать метод get_object.

Вы выполняете запрос GET /str:pk/comments/str:cm/, это вызывает метод retrieve на представлении, который в свою очередь вызывает get_object. Поведение по умолчанию - попытка найти объект Comment с id равным pk, поскольку это первый аргумент, поскольку вам нужно фильтровать через другую модель, вам нужно переписать ее.

classy drf - это хороший сайт для просмотра того, как работают внутренние компоненты классов.

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