0

I have three models where one Document has many Blocks and one Block has many Comments.

class Document(models.Model):
  name = models.Charfield()

class Block(models.Model):
  document = models.ForeignKey(to=Document)

class Comment
  block = models.ForgeinKey(to=Block)

Users can have permissions for Document which allows them to see all Blocks in it. Users can also add Comments to any Block which they can share if other users. I use django-guardian to manage object-based permissions.

I have created a RetrieveAPIView using Django Rest Framework to make the Document available.

class DocumentDetailView(PermissionRequiredMixin, RetrieveAPIView):
    serializer_class = DocumentSerializer
    permission_required = "document.view_document"

To include all blocks and their comments in that view, I use the following serializers (omitted class Meta for brevity):

class DocumentSerializer(serializers.ModelSerializer):
    blocks = BlockSerializer(many=True, source="block_set")

class BlockSerializer(serializers.ModelSerializer):
    comments = serializers.CommentSerializer(many=True, source="comment_set")

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment

I would like to restrict the comments included in DocumentDetailView to those to which a user has permissions. Following the logic of django-guardian I would use get_objects_for_users(), to filter down the QuerySet of Block.comment_set.all(). Yet, I don't know where to do this.

I guess to restrict the comments to those available to request.user, the permission-based filtering should be done in the DocumentDetailView, but I don't see how to do this in get_object().

nehalem
  • 397
  • 2
  • 20

1 Answers1

0

I don't know much about django-guardian but I guess you could override the get_queryset method:

class DocumentDetailView(PermissionRequiredMixin, RetrieveAPIView):
    serializer_class = DocumentSerializer
    permission_required = "document.view_document"

    def get_queryset(self):
        if self.check_permissions():
            queryset = super().get_queryset()
            return queryset.filter(...)  # <- here you permission filter
May.D
  • 1,832
  • 1
  • 18
  • 34
  • Thank you for your answer. Maybe I am mistaken, but I don't think `RetrieveAPIView` even implements `get_queryset()`? Also, using `queryset.filter()` doesn't work well for checking permissions with django-guardian. – nehalem Jun 23 '21 at 14:26
  • `RetrieveAPIView` has get_queryset method for sure as it extend `GenericAPIView`. For filter arguments I don't know the data model of django-gardian, how is it related to User model ? – May.D Jun 23 '21 at 15:02
  • 1
    Did you find a solution ? If not I have a few hours to dig into it as I'm curious about django-guardian. – May.D Jun 23 '21 at 20:52
  • Not yet. I had a look at [django-rest-framework-guardian](https://github.com/rpkilby/) but I don't think it offers a solution. There's also [this question](https://stackoverflow.com/questions/36553197/permission-checks-in-drf-viewsets-are-not-working-right) which is close but not quite my problem. Maybe it'd be best to split up the view and put comments in a different endpoint. – nehalem Jun 24 '21 at 07:58