Reputation: 25
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?
Upvotes: 1
Views: 301
Reputation: 1718
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']
Upvotes: 1