liveBook · Manning

Recursion

As explained in The Well-Grounded Python Developer: How the pros use Python and Flask

Recursion is a technique in which an operation is repeatedly applied to progressively nested or related instances of the same kind of structure.

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

How The Well-Grounded Python Developer: How the pros use Python and Flask covers it

How deep it goes
Explains recursive tree traversal and its stopping and return behavior, then connects it to recursive SQL CTEs without detailing the full query.
Examples
Uses a MyBlog content post with nested comment posts represented as a tree.
What you can do after
Apply recursion via SQLAlchemy and recursive CTEs to retrieve hierarchies from self-referential database tables.
How it connects
Connects recursion with tree structures, self-referential data, common table expressions, SQLAlchemy, and Python.

Also explained in

Compare how 23 books explain recursion →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Well-Grounded Python Developer: How the pros use Python and Flask. The section links point to the parts of the book it draws on.