I am new to django. I'm trying to deal with queries on nested comments. There is a blog project with adding articles and adding comments to articles. For each comment, you can recursively add a comment, and so on.
├── blog_api
│ ├── asgi.py
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├──── blog_api/api
| ├── admin.py
| ├── apps.py
| ├── __init__.py
| ├── migrations
| │ └── __init__.py
| ├── models.py
| ├── permissions.py
| ├── serializers.py
| ├── tests.py
| ├── urls.py
| └── views.py
└── manage.py
I described the following models
api/models.py
from django.db import models
class Article(models.Model):
date_pub = models.DateTimeField(auto_now_add=True)
title = models.CharField (max_length = 60, blank=True, default='')
text = models.TextField(blank=True, default='')
owner = models.ForeignKey('auth.User', related_name='posts', on_delete=models.CASCADE)
class Meta:
ordering = ['date_pub']
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']
api/serializers.py
from rest_framework import serializers
from api.models import Article
from api.models import Comment
from django.contrib.auth.models import User
class ArticleSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
comments = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Article
fields = ['id', 'title', 'text', 'owner', 'comments']
class UserSerializer(serializers.ModelSerializer):
posts = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
comments = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = User
fields = ['id', 'username', 'posts', 'comments']
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']
The GET query returns the following comment structure:
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
[
{
"id": 1,
"text": "First comment",
"owner": "alex",
"article": 1,
"parent": null,
"reply_set": [
{
"id": 2,
"text": "Comment to comment",
"owner": "alex",
"article": 1,
"parent": 1,
"reply_set": []
}
]
},
{
"id": 2,
"text": "Comment to comment",
"owner": "alex",
"article": 1,
"parent": 1,
"reply_set": []
},
{
"id": 3,
"text": "Second article comment",
"owner": "alex",
"article": 2,
"parent": null,
"reply_set": [
{
"id": 4,
"text": "Comment to second article comment",
"owner": "alex",
"article": 1,
"parent": 3,
"reply_set": [
{
"id": 5,
"text": "some comment",
"owner": "alex",
"article": 1,
"parent": 4,
"reply_set": [
{
"id": 6,
"text": "some more comment",
"owner": "alex",
"article": 1,
"parent": 5,
"reply_set": []
}
]
}
]
}
]
},
{
"id": 4,
"text": "Comment to second article comment",
"owner": "alex",
"article": 1,
"parent": 3,
"reply_set": [
{
"id": 5,
"text": "some comment",
"owner": "alex",
"article": 1,
"parent": 4,
"reply_set": [
{
"id": 6,
"text": "some more comment",
"owner": "alex",
"article": 1,
"parent": 5,
"reply_set": []
}
]
}
]
},
{
"id": 5,
"text": "some comment",
"owner": "alex",
"article": 1,
"parent": 4,
"reply_set": [
{
"id": 6,
"text": "some more comment",
"owner": "alex",
"article": 1,
"parent": 5,
"reply_set": []
}
]
},
{
"id": 6,
"text": "some more comment",
"owner": "alex",
"article": 1,
"parent": 5,
"reply_set": []
}
]
I have no idea for solving the following problems:
How to get all comments for this comment, which is at the third nesting level?
How can a tree structure be recreated from the comments API response?
Sending API request localhost:8000/comments/1 I receive the comment with id="1" and all nested comments to the third level. How to make request getting the third level nesting comment and all others? What should be written in views and urls?
CodePudding user response:
Could you check if this code works for you?
class FinalLevelRepliesSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Comment
fields = ['id', 'text', 'owner', 'article', 'parent']
class FirstLevelRepliesSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
reply_set = FinalLevelRepliesSerializer(many=True, read_only=True)
class Meta:
model = Comment
fields = ['id', 'text', 'owner', 'article', 'parent', 'reply_set']
class CommentSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
reply_set = FirstLevelRepliesSerializer(many=True, read_only=True)
class Meta:
model = Comment
fields = ['id', 'text', 'owner', 'article', 'parent', 'reply_set']