我的Django项目中有下一个模型。
models.py:
class Document(models.Model):
name = models.TextField(blank=True, null=True)
def get_children(self):
return [dc.child for dc in DocumentClosure.objects.filter(parent=self)]
class DocumentClosure(models.Model):
parent = models.ForeignKey(
Document,
on_delete=models.CASCADE,
related_name="closures_as_parent",
db_column='parent_id',
blank=True,
null=True
)
child = models.ForeignKey(
Document,
on_delete=models.CASCADE,
related_name="closures_as_child",
db_column='child_id',
blank=True,
null=True
)
level = models.IntegerField(
default=0,
blank=True,
null=True
)
下一个模型使用"Closure Table"
架构在数据库中创建2个表。
DocumentClosure 存储有关祖先和后代的信息。我希望在模板中显示树,因为它使django-mptt
应用程序。
我开始使用下一个代码。现在我需要根据我当前的模型重写get_children()
方法。有人可以用这种方法帮助我吗?!
模板:
<ul>
{% recursetree documents %}
<li>
{{ node.name }}
<ul class="children">
{{ children }}
</ul>
</li>
{% endrecursetree %}
</ul>
custom_tag.py:
from django import template
register = template.Library()
@register.tag
def recursetree(parser, token):
bits = token.contents.split()
if len(bits) != 2:
raise template.TemplateSyntaxError(_('%s tag requires a queryset') % bits[0])
queryset_var = template.Variable(bits[1])
template_nodes = parser.parse(('endrecursetree',))
parser.delete_first_token()
return RecurseTreeNode(template_nodes, queryset_var)
class RecurseTreeNode(template.Node):
def __init__(self, template_nodes, queryset_var):
self.template_nodes = template_nodes
self.queryset_var = queryset_var
def _render_node(self, context, node):
bits = []
context.push()
for child in node.get_children(): # get_children() initialized in models.py file | rewrite this method
bits.append(self._render_node(context, child))
context['node'] = node
context['children'] = mark_safe(''.join(bits))
rendered = self.template_nodes.render(context)
context.pop()
return rendered
def render(self, context):
queryset = self.queryset_var.resolve(context)
roots = queryset
bits = [self._render_node(context, node) for node in roots]
return ''.join(bits)
修改
在控制台中python manage.py runserver
命令后,我看到对数据库的无休止的重复查询。但一段时间后它会引发错误:
Traceback (most recent call last):
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/handlers/base.py", line 217, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/handlers/base.py", line 215, in _get_response
response = response.render()
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/response.py", line 107, in render
self.content = self.rendered_content
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/response.py", line 84, in rendered_content
content = template.render(context, self._request)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/backends/django.py", line 66, in render
return self.template.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 207, in render
return self._render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 199, in _render
return self.nodelist.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
bit = node.render_annotated(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
return self.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 177, in render
return compiled_parent._render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 199, in _render
return self.nodelist.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
bit = node.render_annotated(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
return self.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 177, in render
return compiled_parent._render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 199, in _render
return self.nodelist.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
bit = node.render_annotated(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
return self.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 72, in render
result = block.nodelist.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
bit = node.render_annotated(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
return self.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 72, in render
result = block.nodelist.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
bit = node.render_annotated(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
return self.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 216, in render
return template.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 209, in render
return self._render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 199, in _render
return self.nodelist.render(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
bit = node.render_annotated(context)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
return self.render(context)
File "/Applications/Projects/web/project/documents/templatetags/documents_tags.py", line 41, in render
bits = [self._render_node(context, node) for node in roots]
File "/Applications/Projects/web/project/documents/templatetags/documents_tags.py", line 31, in _render_node
bits.append(self._render_node(context, child))
File "/Applications/Projects/web/project/documents/models.py", line 117, in get_children
return [dc.child for dc in DocumentClosure.objects.filter(parent=self)]
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/query.py", line 250, in __iter__
self._fetch_all()
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/query.py", line 1118, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/query.py", line 53, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 871, in execute_sql
sql, params = self.as_sql()
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/backends/oracle/compiler.py", line 21, in as_sql
with_col_aliases=with_col_aliases,
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 436, in as_sql
where, w_params = self.compile(self.where) if self.where is not None else ("", [])
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 373, in compile
sql, params = node.as_sql(self, self.connection)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/sql/where.py", line 79, in as_sql
sql, params = compiler.compile(child)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 373, in compile
sql, params = node.as_sql(self, self.connection)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/fields/related_lookups.py", line 127, in as_sql
return super(RelatedLookupMixin, self).as_sql(compiler, connection)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/lookups.py", line 169, in as_sql
lhs_sql, params = self.process_lhs(compiler, connection)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/lookups.py", line 162, in process_lhs
db_type = self.lhs.output_field.db_type(connection=connection)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/fields/related.py", line 991, in db_type
return self.target_field.rel_db_type(connection=connection)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 951, in rel_db_type
return IntegerField().db_type(connection=connection)
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 166, in __init__
if isinstance(choices, collections.Iterator):
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/bin/../lib/python2.7/abc.py", line 141, in __instancecheck__
subtype in cls._abc_negative_cache):
File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/bin/../lib/python2.7/_weakrefset.py", line 75, in __contains__
return wr in self.data
RuntimeError: maximum recursion depth exceeded in cmp
让我说我有这样的树。 示例:
A
|
- B
|
- C
文档表:
id | parent_id | name
1 | | A
2 | 1 | B
3 | 2 | C
最后 document_closure 表:
id | parent_id | child_id | level
1 | 1 | 1 | 0
2 | 2 | 2 | 0
3 | 3 | 3 | 0
4 | 1 | 2 | 1
5 | 2 | 3 | 1
6 | 1 | 3 | 2
答案 0 :(得分:0)
选择DocumentClosure
为Document
的所有parent
个对象并返回其子女。
返回列表及其关联的子Document
,如下所示:
class Document(models.Model):
name = models.TextField(blank=True, null=True)
def get_children(self):
return [dc.child for dc in DocumentClosure.objects.filter(parent=self)]
您应该考虑在related_name
上重命名ForeignKey
两个DocumentClosure
关系 - 它们会创建名称混乱的属性。 Document.parents
返回Queryset
个DocumentClosure
个对象,其中给定的Document
是父对象。人们会期望它包括当前文件的父母。也许像closures_as_parent
和closures_as_child
这样的东西更合适。