A minimal Python Tkinter Parent-Children Data Form

I've made an example Python program that does nothing more than load two tables into a form and then lets you filter the "child" records by selecting rows in the "parent" table.

The idea here is to show a minimal-imports method of displaying parent-child records using the stock Tkinter and SQLite Python libraries.

In short: you can find the code at this online Git repository where there's really just the one Python file.

Here's how it looks:

It came about after I recently watched a YouTube video by Data Analytics Ireland. My many thanks to them for sharing that, but I wasn't pleased with the amount of code I had to wade through just to find the parts that made and loaded the records and then responded to which was clicked. I also felt a chance was missed to enact a parent-child behaviour between the two tables.

I first made my own rebuild as a way to test what I'd gleaned - using my usual stock interfacing (that's elsewhere in my GitLab presence). But then I decided it was unfair of me to moan about examples having unnecessary things in them - unless I tried doing that myself.

I'll let the README at the respository speak for itself, but will here discuss some of the vital parts. I won't cover the SQLite parts, so I'm assuming the simple SQL SELECT statements are familiar - but do ask if you'd like those explained.

Here's the definition of the parent display control - using a Tkinter Treeview with added scoll bars and an action binding for when a row is selected.

# Parent records Treeview, scrollbars
    tk_trvw_prnt = im_tkntr_ttk.Treeview( tk_frame_prnt_data)
    tk_trvw_prnt.place( relheight=1.0, relwidth=1.0)
    # adding scrollbars
    tk_trvw_prnt_treescrolly = im_tkntr.Scrollbar(tk_frame_prnt_data, orient="vertical", command=tk_trvw_prnt.yview)
    tk_trvw_prnt_treescrollx = im_tkntr.Scrollbar(tk_frame_prnt_data, orient="horizontal", command=tk_trvw_prnt.xview)
    tk_trvw_prnt.configure( xscrollcommand=tk_trvw_prnt_treescrollx.set, yscrollcommand=tk_trvw_prnt_treescrolly.set)
    tk_trvw_prnt_treescrollx.pack(side="bottom", fill="x")
    tk_trvw_prnt_treescrolly.pack(side="right", fill="y")
    tk_trvw_prnt.bind("<<TreeviewSelect>>", Cmd_trvw_prnt_on_tree_select)

Here's how the "parent" Treevew gets loaded, from two lists that were loaded via SQLite: a_rows & a_names for the data and column names.

a_didok, a_rows, a_names = SqLite_Filename_GetTable_Rows( ExampleDetail_Database_Filename(), ExampleDetail_Parent_Tablename() )
        tk_trvw_prnt["column"] = a_names
        tk_trvw_prnt["show"] = "headings"
        for column in tk_trvw_prnt["columns"]:
            tk_trvw_prnt.heading(column, text=column)
        for row in a_rows:
            tk_trvw_prnt.insert("", "end", values=row)

Of course, if we're reloading a table we'll need to clear the TreeView first, and that's done with the following (doing the "parent" again to go with the above):

for i in tk_trvw_prnt.get_children():
            tk_trvw_prnt.delete(i)

Choosing to the reload the chld table is a matter of constructing a new SQL SELECT with a WHERE clause - but how do we get the value to use?

Here's how I wrote that step - into a separate function as I toyed with it, and done in small steps as I worked them out.

def GetCurrentParentKey():
        slctn_prnt = tk_trvw_prnt.selection()
        curItem = tk_trvw_prnt.focus()
        curParts = tk_trvw_prnt.item( curItem)
        curRow = curParts[ "values"]
        clms_idx_pky = tk_trvw_prnt["column"].index(ExampleDetail_Parent_LinkColumnName())
        pkyval = curRow[ clms_idx_pky ]
        return pkyval

Doubtless, people with better Python skills than mine could reduce that to something much shorter and harder to follow.

p.s. I didn't want to post the whole code here, even though it will probably fit well enough in a Dev post - I just didn't want to be updating it in two places if I make changes.

14