Home > front end >  How does Django query the tree structure
How does Django query the tree structure

Time:11-11

I am new to Django and I am creating a blog and comment function

from django.db import models
from django.contrib.auth import get_user_model


class Blog(models.Model):
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    content = models.TextField(max_length=200)


class Comment(models.Model):
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
    parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name="children")
    content = models.CharField(max_length=200)

This is my current test data

Comment.objects.all().values()
<QuerySet [
{'id': 1, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '1'}, 
{'id': 2, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '2'}, 
{'id': 3, 'user_id': 1, 'blog_id': 1, 'parent_id': 1,    'content': '1-1'}, 
{'id': 4, 'user_id': 1, 'blog_id': 1, 'parent_id': 1,    'content': '1-2'}
]>

But now I want to find out such a tree structure, what should I do?

[
 {'id': 1, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '1', 'children': [
            {'id': 3, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '1-1'},
            {'id': 4, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '1-2'}
        ]},
 {'id': 2, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '2', 'children': [] },
]

CodePudding user response:

You can' t obtain a nested dictionary with values. You could write this:

Comment.objects.all().values('id', 'user_id', 'blog_id', 'parent_id', 'content', 'children')

But the result will not be as you expected, the list will contain a dict for every parent-child combination, for example:

[
{'id': 1, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '1', children: 2}, 
{'id': 1, 'user_id': 1, 'blog_id': 1, 'parent_id': None, 'content': '1', children: 3}, 
{'id': 2, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '2', children: None}, 
{'id': 3, 'user_id': 1, 'blog_id': 1, 'parent_id': 1, 'content': '2', children: None}, 
]

You can deal directly with the queryset, for example:

for comment in Comment.objects.all().prefetch_related('children'):
    for child in comment.children.all():
        print(child.id)

Or you can use a nested list comprehension (the result will be as you expected):

print([{'id': comment.id, 'user_id': comment.user.id, 'blog_id': comment.blog.id, 'parent_id': comment.parent.id if comment.parent != None else None, 'content': comment.content, 'children': [{'id':
child.id, 'user_id': child.user.id, 'blog_id': child.blog.id, 'parent_id': child.parent.id, 'content': child.content} for child in comment.children.all()]} for comment in Comment.objects.all()])

CodePudding user response:

I use recursion to query

def get_children(c):
    return {
        'id': c.id,
        'user_id': c.user_id,
        'blog_id': c.blog_id,
        'parent_id': c.parent_id,
        'content': c.content,
        'children': list(map(get_children, c.children.all())),
    }


def get_comment_tree():
    return list(map(get_children, Comment.objects.filter(parent=None).prefetch_related('children')))

Output json

[{
    "id": 1,
    "user_id": 1,
    "blog_id": 1,
    "parent_id": null,
    "content": "1",
    "children": [{
        "id": 3,
        "user_id": 1,
        "blog_id": 1,
        "parent_id": 1,
        "content": "1-1",
        "children": [{
            "id": 5,
            "user_id": 1,
            "blog_id": 1,
            "parent_id": 3,
            "content": "1-1-1",
            "children": []
        }]
    }, {
        "id": 4,
        "user_id": 1,
        "blog_id": 1,
        "parent_id": 1,
        "content": "1-2",
        "children": []
    }]
}, {
    "id": 2,
    "user_id": 1,
    "blog_id": 1,
    "parent_id": null,
    "content": "2",
    "children": []
}]
  • Related