Django Rest Framework Объект, принадлежащий пользователю: изменение связанного объекта

Предположим, у меня есть модели типа:

class Book(models.Model):
    title = models.CharField(max_length=254)
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)

class Chapter(models.Model):
    title = models.CharField(max_length=254)
    book = models.ForeignKey(Book, on_delete=models.CASCADE)

Предположим, пользователь A создает книгу. Я могу ограничить доступ к книге от пользователя B в наборе представлений Book, переопределив get_queryset:

 def get_queryset(self):
     user = User.objects.get(username=self.request.user.username)
     queryset = Book.objects.filter(user=user)
     return queryset

У меня также есть конечная точка для добавления глав:

class ChapterViewSet(viewsets.ModelViewSet):
    queryset = Chapter.objects.all()
    serializer_class = serializers.ChapterSerializer
    model = Chapter

Я хочу запретить пользователю B добавлять (создавать, POST) главы в книгу, созданную пользователем A. Какова наилучшая практика для создания такого ограничения?

Я бы определенно сделал это на уровне сериализатора с валидацией...

https://www.django-rest-framework.org/api-guide/serializers/#validation

Итак, если ваш сериализатор выглядит примерно так, я бы сделал так:

class ChapterSerializer(serializers.ModelSerializer):
    class Meta:
        model = Chapter
        fields = ['id', 'title', 'book']

    def validate_book(self, value):
       if not Book.objects.filter(id=value, user=self.context['request'].user).exists():
           raise serializers.ValidationError("This is not your book.")

Этого можно достичь, переписав метод perform_create. Вы также должны изменить метод get_queryset, чтобы достичь того, что вы ищете. Вы можете сделать что-то вроде:

# your_app/views.py

from rest_framework import exceptions, viewsets

from .models import Book, Chapter


class ChapterViewSet(viewsets.ModelViewSet):
    queryset = Chapter.objects.all()
    serializer_class = serializers.ChapterSerializer
    model = Chapter

    def get_queryset(self):
        return Chapter.objects.filter(book__user=self.request.user)

    def perform_create(self, serializer):
        book = serializer.validated_data['book']
        if book.user != self.request.user:
            raise exceptions.PermissionDenied("Only book owners can add chapter to it.")
        serializer.save()

Теперь при вызове API, который пытается добавить главу в книгу, не созданную аутентифицированным пользователем, в ответ возвращается ошибка 403 Permission Denied.

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