snippetpythondjangoMinor
Recursive Django filter to output a list from user hierarchy
Viewed 0 times
djangohierarchyuseroutputrecursivefilterlistfrom
Problem
I need to create an HTML unordered list (to display with jstree) to display the hierarchy of users, along with a list underneath the user's "subusers" of their comments. Each user could have many users underneath him, and each of those users could have the same, so I used a recursive filter to accomplish this. However, this has lead to code that feels very repetitive, besides small differences, and it seems to me that surely something could be reduced. I have already identified some repeated code (extracted to
Note before the code:
Finally, I would appreciate any other pointers, since this is my first filter. It seems straightforward enough, but for all I know this could be a completely inappropriat
_output_comments below), but I would hope I could do more somehow.Note before the code:
User has a foreign key to itself, with subusers as the related_name, and Comment has a foreign key to User.from django import template
register = template.Library()
@register.filter
def unordered_user_list(user):
"""
Takes a user and returns an HTML unordered list (without surrounding tags) of
users and comments under it.
"""
html = ""
if len(user.subusers.all()) > 0:
html += "" + user.name
if len(user.comment_set.all()) > 0:
html += ""
for subuser in user.subusers.all():
html += unordered_user_list(subuser)
html += "Comments"
html += _output_comments(user.comment_set.all())
else:
for subuser in user.subusers.all():
html += "" + unordered_user_list(subuser) + ""
html += ""
elif len(user.comment_set.all()) > 0:
html += "" + user.name + "Comments"
html += _output_comments(user.comment_set.all())
else:
html += "" + user.name + ""
return html
def _output_comments(comment_list):
output = ""
for comment in comment_list:
output += "" + comment.name + ""
output += ""
return outputFinally, I would appreciate any other pointers, since this is my first filter. It seems straightforward enough, but for all I know this could be a completely inappropriat
Solution
First of all, you can move the first
Then,
I think that the way you add
Overall, you should try to write Python code whose structures more or less reflects the structure of the HTML code you are writing. That will avoid tricky mistakes and tag mismatches. When I read your code as is, I have trouble knowing whether there are tags mismatches or not.
out of the first if condition. That allows you to totally get rid of the last else:html = "" + user.name
if len(user.subusers.all()) > 0:
# ...
elif len(user.comment_set.all()) > 0:
html += "Comments"
# ...
# don't add the last here
html += "" # add it there instead
return htmlThen,
_output_comments should handle the whole comment stuff, including the heading:def _output_comments(comment_list):
output = "Comments"
for comment in comment_list:
output += "" + comment.name + ""
output += ""
return outputI think that the way you add
and `` tags does not reflect the structure of the page. You should improve this:def _output_comments(comment_list):
output = ("" +
"Comments" +
"")
for comment in comment_list:
output += "" + comment.name + ""
output += ("" +
"" +
"")
return outputOverall, you should try to write Python code whose structures more or less reflects the structure of the HTML code you are writing. That will avoid tricky mistakes and tag mismatches. When I read your code as is, I have trouble knowing whether there are tags mismatches or not.
Code Snippets
html = "<li id='user-" + str(user.id) + "'>" + user.name
if len(user.subusers.all()) > 0:
# ...
elif len(user.comment_set.all()) > 0:
html += "<ul><li>Comments<ul>"
# ...
# don't add the last </li> here
html += "</li>" # add it there instead
return htmldef _output_comments(comment_list):
output = "<li>Comments<ul>"
for comment in comment_list:
output += "<li id='comment-" + str(comment.id) + "'>" + comment.name + "</li>"
output += "</ul></li></ul>"
return outputdef _output_comments(comment_list):
output = ("<li>" +
"Comments" +
"<ul>")
for comment in comment_list:
output += "<li id='comment-" + str(comment.id) + "'>" + comment.name + "</li>"
output += ("</ul>" +
"</li>" +
"</ul>")
return outputContext
StackExchange Code Review Q#58791, answer score: 2
Revisions (0)
No revisions yet.