Danny
Danny

Reputation: 337

How to hide certain json data from passing through if it doesn't meet a condition in Django rest framework?

Hello all I want to hide certain json data from passing through if it doesn't meet a condition in django rest framework, like I have a comment model and serializer, and I don't want the replies to pass through as comments since I have another field for replies which is nested along with the respective comments.

These are the serializers:

class CommentCreateSerializer(serializers.ModelSerializer):
    content         = serializers.CharField()
    reply_id        = serializers.PrimaryKeyRelatedField(source='reply',queryset=Comment.objects.all(),
                            write_only=True, required=False)    
    user            = serializers.ReadOnlyField(source="user.username")

    class Meta:
        model       = Comment
        fields      = ['id', 'user', 'content', 'reply_id', 'timestamp']

class CommentSerializer(serializers.ModelSerializer):
    content         = serializers.CharField()
    reply_id        = serializers.PrimaryKeyRelatedField(source='reply',queryset=Comment.objects.all(),
                            required=False)
    user            = serializers.ReadOnlyField(source="user.username")
    replies         = CommentCreateSerializer(many=True, read_only=True)

    class Meta:
        model       = Comment
        fields      = ['id', 'user', 'content', 'replies', 'reply_id', 'timestamp']

This is the current json response:

"count": 5,
"next": null,
"previous": null,
"results": [
    {
        "id": 2,
        "user": "testuser2",
        "content": "comment test!",
        "replies": [
            {
                "id": 3,
                "user": "testuser3",
                "content": "ding",
                "timestamp": "2021-02-09T15:29:38.230933+01:00"
            }
        ],
        "reply_id": null,
        "timestamp": "2021-02-09T15:24:11.072502+01:00"
    },

    {
        "id": 3,
        "user": "testuser3",
        "content": "ding",
        "replies": [],
        "reply_id": 2,
        "timestamp": "2021-02-09T15:29:38.230933+01:00"
    },
]
}

This is what I need.

"count": 5,
"next": null,
"previous": null,
"results": [
    {
        "id": 2,
        "user": "testuser2",
        "content": "comment test!",
        "replies": [
            {
                "id": 3,
                "user": "testuser3",
                "content": "ding",
                "timestamp": "2021-02-09T15:29:38.230933+01:00"
            }
        ],
        "reply_id": null,
        "timestamp": "2021-02-09T15:24:11.072502+01:00"
    },

]
}

UPDATE:

models.py

class Comment(models.Model):
    user            = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    post            = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="post_comments") 
    reply           = models.ForeignKey('Comment', null=True, related_name='replies', blank=True, on_delete=models.CASCADE)
    content         = models.TextField(max_length=1000)
    timestamp       = models.DateTimeField(auto_now_add=True)

views.py

class CommentPostAPIView(APIView):
    permission_classes = (IsAuthenticated,) 
    # pagination_class = PageNumberPagination

    def get(self, *args, **kwargs):
        post                = get_object_or_404(Post, slug=self.kwargs['slug'])
        comments            = Comment.objects.filter(post=post)
        paginator           = CustomPaginator()
        response            = paginator.generate_response(comments, CommentSerializer, self.request)
        return response

Here I want to hide the replies from showing up along with the comments as replies are already nested along with respective comments. so comments with reply_id are actually replies and one with null reply_id's are comments. How can I prevent those from passing through.

Thank you

Upvotes: 1

Views: 384

Answers (4)

edilio
edilio

Reputation: 1868

In your case you need to filter as @Chandan said before. So really you need to refactor your view with the reply_id filter

    permission_classes = (IsAuthenticated,) 
    # pagination_class = PageNumberPagination

    def get(self, *args, **kwargs):
        post                = get_object_or_404(Post, slug=self.kwargs['slug'])
        comments            = Comment.objects.filter(post=post,reply_id__isnull=True)
        paginator           = CustomPaginator()
        response            = paginator.generate_response(comments, CommentSerializer, self.request)
        return response

Upvotes: 0

Chandan
Chandan

Reputation: 11807

Your CommentSerializer is correct problem is you are getting all comments and related replies from Comment model in your view and passing to CommentSerializer you need to filter and remove reply related to comment

Comment.objects.filter(reply_id__isnull=True)

Upvotes: 1

Shubham Sarda
Shubham Sarda

Reputation: 635

Serializers validation will work fine in this case. If you need to add a condition to a specific field then create a method validate_fieldname and if you want to add condition over a specific object then directly create a method as validate.

You can read the documentation for more information - https://www.django-rest-framework.org/api-guide/serializers/#field-level-validation

Upvotes: 0

JPG
JPG

Reputation: 88569

set reply_id field as write_only

class CommentSerializer(serializers.ModelSerializer):
    content = serializers.CharField()
    reply_id = serializers.PrimaryKeyRelatedField(
        source='reply',
        queryset=Comment.objects.all(),
        required=False,
        write_only=True
    )
    user = serializers.ReadOnlyField(source="user.username")
    replies = CommentCreateSerializer(many=True, read_only=True)

    class Meta:
        model = Comment
        fields = ['id', 'user', 'content', 'replies', 'reply_id', 'timestamp']

Upvotes: 0

Related Questions