Recursion becomes useful when identical items form a hierarchy, such as a post with nested comments. Each node can reuse the same processing until the tree is fully traversed. section 11.7.2
A recursive traversal follows a repeatable pattern:
- Start at the root post and inspect its associated children. section 11.7.2
- Apply the same operation to each child, descending through progressively nested comments. section 11.7.2
- Stop descending at a node with no children, then return to its parent and process the next child. section 11.7.2
- Continue until every node attached to the content root has been visited. section 11.7.2
Nested comments in MyBlog
A content post acts as the root of a tree, while comment posts branch from it and may have further children. The display handler retrieves the hierarchy and renders the post with its comments in meaningful order. section 11.7.2
def _build_posts_hierarchy(db_session, post_uid):
# build the list of filters here to use in the CTE
filters = [ #1
Post.post_uid == post_uid, #1
Post.parent_uid == None #1
] #1
if current_user.is_anonymous or #2
current_user.can_view_posts(): #2
filters.append(Post.active == True) #2
# build the recursive CTE query
hierarchy = ( #3
db_session #3
.query(Post, Post.sort_key.label( #3
"sorting_key")) #3
.filter(*filters) #3
.cte(name=‘hierarchy’, recursive=True) #3
) #3
children = aliased(Post, name="c") #4
hierarchy = hierarchy.union_all( #5
db_session #5
.query( #5
children, #5
( #5
func.cast(hierarchy.c.sorting_key, #5
String) + #5
" " + #5
func.cast(children.sort_key, #5
String) #5
).label("sorting_key") #5
) # #5
.filter(children.parent_uid == #5
hierarchy.c.post_uid) #5
)
# query the hierarchy for the post
and it’s comments
return ( #6
db_session #6
.query(Post, func.cast( #6
hierarchy.c.sorting_key, String)) #6
.select_entity_from(hierarchy) #6
.order_by(hierarchy.c.sorting_key) #6
.all() #6
) #6
Inspect the hierarchy-building query, which uses SQLAlchemy to begin a recursive common table expression for the self-referential post structure. section 11.7.2
def blog_post_display(post_uid):
logger.debug("rendering blog post page")
form = PostCommentForm()
with db_session_manager() as db_session:
posts = _build_posts_hierarchy(db_session, post_uid)
if posts is None:
flash(f"Unknown post uid: {post_uid}")
abort(HTTPStatus.NOT_FOUND)
return render_template("post.html", form=form, posts=posts)
Follow the display handler as it opens a database session, builds the post hierarchy, handles an unknown post, and renders the result. section 11.7.2






















