Reputation: 25
I have a blog on django. I have two models article and comment. Each comment can be added to another one. If I send an API request localhost:8000/comments/1 I receive the comment with id="1" and all the nested comments to the third level.
json after api request localhost:8000/comments/ :
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
[
{
"id": 9,
"text": "First comment",
"owner": "alex",
"article": 3,
"parent": null,
"reply_set": [
{
"id": 10,
"text": "Comment to comment",
"owner": "alex",
"article": 3,
"parent": 9,
"reply_set": [
{
"id": 11,
"text": "Third level nested comment",
"owner": "alex",
"article": 3,
"parent": 10
}
]
}
]
},
{
"id": 10,
"text": "Comment to comment",
"owner": "alex",
"article": 3,
"parent": 9,
"reply_set": [
{
"id": 11,
"text": "Third level nested comment",
"owner": "alex",
"article": 3,
"parent": 10,
"reply_set": [
{
"id": 12,
"text": "Forth level nested comment",
"owner": "alex",
"article": 3,
"parent": 11
}
]
}
]
},
{
"id": 11,
"text": "Third level nested comment",
"owner": "alex",
"article": 3,
"parent": 10,
"reply_set": [
{
"id": 12,
"text": "Forth level nested comment",
"owner": "alex",
"article": 3,
"parent": 11,
"reply_set": []
}
]
},
{
"id": 12,
"text": "Forth level nested comment",
"owner": "alex",
"article": 3,
"parent": 11,
"reply_set": []
}
]
How to receive the third level comment with all others nested comment? What should I write in views and urls?
Comment model:
class Comment(models.Model):
date_pub = models.DateTimeField(auto_now_add=True)
text = models.TextField(blank=False)
owner = models.ForeignKey('auth.User', related_name='comments', on_delete=models.CASCADE)
article = models.ForeignKey('Article', related_name='comments', on_delete=models.CASCADE)
parent = models.ForeignKey('self', related_name='reply_set', null=True, on_delete=models.PROTECT)
class Meta:
ordering = ['date_pub']
Comment serializer:
class RecursiveSerializer(serializers.Serializer):
def to_representation(self, value):
serializer = self.parent.parent.__class__(value, context=self.context)
return serializer.data
class CommentSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
reply_set = RecursiveSerializer(many=True, read_only=True)
class Meta:
model = Comment
fields = ['id', 'text', 'owner', 'article', 'parent', 'reply_set']
Comment views
class CommentList(generics.ListCreateAPIView):
queryset = Comment.objects.all()
serializer_class = serializers.CommentSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class CommentDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Comment.objects.all()
serializer_class = serializers.CommentSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly]
In urlpatterns:
path('comments/', views.CommentList.as_view()),
path('comments/<int:pk>/', views.CommentDetail.as_view())
Upvotes: 0
Views: 47
Reputation: 167
if your question is how can you receive all 3rd level comments (without their parents just the third level comments) of a specific 1st level comment, then you could filter the queryset like this
third_level_comment = Comment.objects.filter(replay_set__replay_set__id = <the 1st level comment id>)
you use the double under score "__" to go up a level on the relation chain
Upvotes: 1