Django如何查询树结构
How does Django query the tree structure
我是 Django 的新手,我正在创建博客和评论功能
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)
这是我目前的测试数据
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'}
]>
但是我现在想找出这样一个树结构,怎么办呢?
[
{'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': [] },
]
您无法使用 values
获取嵌套字典。
你可以这样写:
Comment.objects.all().values('id', 'user_id', 'blog_id', 'parent_id', 'content', 'children')
但结果不会像你预期的那样,列表将包含每个父子组合的字典,例如:
[
{'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},
]
可以直接对queryset进行处理,例如:
for comment in Comment.objects.all().prefetch_related('children'):
for child in comment.children.all():
print(child.id)
或者你可以使用嵌套列表理解(结果将如你所料):
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()])
我用递归查询
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')))
输出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": []
}]
我是 Django 的新手,我正在创建博客和评论功能
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)
这是我目前的测试数据
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'}
]>
但是我现在想找出这样一个树结构,怎么办呢?
[
{'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': [] },
]
您无法使用 values
获取嵌套字典。
你可以这样写:
Comment.objects.all().values('id', 'user_id', 'blog_id', 'parent_id', 'content', 'children')
但结果不会像你预期的那样,列表将包含每个父子组合的字典,例如:
[
{'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},
]
可以直接对queryset进行处理,例如:
for comment in Comment.objects.all().prefetch_related('children'):
for child in comment.children.all():
print(child.id)
或者你可以使用嵌套列表理解(结果将如你所料):
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()])
我用递归查询
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')))
输出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": []
}]