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
.