0

So I building a blog rest_api which has models

class Post(models.Model):
     author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
     text = models.TextField()
     approved = models.BooleanField(default=False)
     ...

class Comment(models.Model):
    reply_to = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    text = models.TextField()
    approved = models.BooleanField(default=False)

As you see both posts and comments have to be approved, posts have to be approved by admins and comments have to be approved by post owners. Also, a user who creates a post has the ability to delete, put and patch fields expect the approved field which can only be patched a superuser.

Same with the comments they can be created by anyone but can only be approved by post owners and superuser. So far here are my serialisers.

class CommentSerializers(ModelSerializer):
    class Meta:
        model = Comment
        fields = ['id','text', 'author']
        read_only_fields = ['author']
    
class PostSerializers(ModelSerializer):
    comments = CommentSerializers(source='comment_set', many=True, read_only=True)

    class Meta:
        model = Post
        fields = [ 'id', 'text', 'author', 'approved', 'comments',]
        read_only_fields = ['author', 'approved',]


    def create(self,validated_data):
        user =  self.context['request'].user
        instance=Post.objects.create(author=user ,**validated_data)
        return instance

And here are my views and permissions

Views:

class PostListView(ListCreateAPIView):
    permission_classes = [IsAuthenticated|ReadOnly]
    serializer_class = PostSerializers

    def perform_create(self, serializer):
        serializer.save()
    def get_queryset(self):
        return Post.objects.filter(approved=True ).order_by('-published_date')

class PostDetailView(RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAuthenticated|ReadOnly]

    serializer_class = PostSerializers
    lookup_field = "id"

    def get_queryset(self):
        return Post.objects.filter(approved=True)


class CommentListView(ListCreateAPIView):
    serializer_class = CommentSerializers
    permission_classes = [IsAuthenticated|ReadOnly]

    def perform_create(self, serializer):
        post_id = self.kwargs['post_id']
        post=Post.objects.get(id = post_id)
        user =  self.request.user
        serializer.save(reply_to = post, author=user )

    def get_queryset(self):
        post_id = self.kwargs['post_id']
        return Comment.objects.filter(reply_to=post_id ,approved=True)

class CommentDetailView(RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAuthenticated|ReadOnly]
    serializer_class = CommentSerializers
    lookup_field = "id"
    def get_queryset(self):
        return Comment.objects.filter(approved=True)

Permissions:

class ReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS
class IsSuperUser(BasePermission):

    def has_permission(self, request, view):
        return request.user and request.user.is_superuser

class IsOwner(BasePermission):

    def has_object_permission(self, request, view, obj):
        if request.user:
            if request.user.is_superuser:
                return True
            else:
                return obj.author == request.user
        else:
            return False

class IsOwnerOfPost(BasePermission):
    def has_object_permission(self,request, view, obj):
        if request.user:
            if request.user.is_superuser:
                return True
            else:
                return obj.post.author == request.user
        else:
            return False
iamafasha
  • 848
  • 10
  • 29
  • 1
    I think this can help you: https://stackoverflow.com/questions/19128793/per-field-permission-in-django-rest-framework – Sajad Dec 03 '20 at 22:46
  • 1
    You should create a separate action endpoint in your views for comment and post approval. In that way you can decouple it from the main endpoint and have simpler permissions – Ken4scholars Dec 04 '20 at 02:04
  • The answer provided in the link @Sajad provided works has for me. Is it possible to apply permission classes conditionally? – iamafasha Dec 04 '20 at 06:29

0 Answers0