Я проделал некоторую работу, следуя учебнику по django. Я хотел бы добавить возможность сделать фрагмент частным, чтобы другие пользователи его не увидели. Я создал дополнительное поле для фрагмента и попытался реализовать это с помощью прав доступа к объектам. Он работает так, что другие пользователи не видят его в подробном представлении (403 запрещено), и после переопределения метода list в ViewSet для его фильтрации он больше там не отображается. Тем не менее, он по-прежнему указан в разделе пользователя, поскольку это связанное поле.
Как отфильтровать его из представления пользователя, чтобы API возвращал только ресурсы, которые может видеть текущий пользователь.
У меня есть models.py вот так:
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
...
private = models.BooleanField(default=False)
serializers.py:
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
highlight = serializers.HyperlinkedIdentityField(
view_name='snippet-highlight', format='html')
class Meta:
model = Snippet
fields = ('url', 'id', 'highlight', 'owner', 'title', 'code',
'linenos', 'language', 'style', 'private')
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = serializers.HyperlinkedRelatedField(
many=True, view_name='snippet-detail', read_only=True)
class Meta:
model = User
fields = ('url', 'id', 'username', 'snippets')
views.py:
class SnippetViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
Additionally we also provide an extra `highlight` action.
"""
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = (
permissions.IsAuthenticatedOrReadOnly,
SeeSnippet, )
def list(self, request):
queryset = Snippet.objects.filter(Q(owner=self.request.user) | Q(private=False))
serializer = SnippetSerializer(queryset, many=True,
context={'request': self.request})
return Response(serializer.data)
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
This viewset automatically provides `list` and `detail` actions.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
permissions.py:
class SeeSnippet(permissions.BasePermission):
"""
Custom permission to only allow owners of an object to edit it.
"""
def has_object_permission(self, request, view, obj):
# If the object is private, then check if the user is the owner.
# Reject if not as non-owners should not be able to see it.
if obj.private:
return obj.owner == request.user
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions are only allowed to the owner of the snippet.
return obj.owner == request.user