Designing a Beginner Level CLI with Python
Published: 2024-02-09 00:32:07

As I have learned Python over the last couple of months, one big challenge I ran into was designing a good CLI (command line interface). Many popular ORM (object-relational mapping) tools such as Django and SQLAlchemy allow you essentially bypass the need to create an ORM and CLI yourself. Thus, there isn't much information out there on how to do it all manually. With my journey through Python and SQL almost complete, I would love to share some information that might help make it easier for you to learn. 

First thing to address is how it is all connected. We can start with python models which will become essentially databases. In these models, we write a mixture of python and SQL to produce methods. These methods do things. They interact with the database. They add rows of information that we need. They delete, modify, find, etc, whatever we want. Some of the most basic methods you would find in this would be create (either create the database or rows), get_all, and delete. Like so. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/all55tekym6zlpre0lu1.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wo1bwp4wqsng72r7mojy.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1ef1yjoxxgmty5odeop.png)

There is nothing special added to these but they are essential. Seeing these is great but they don’t actually do anything until we tell them. Once we have created a number of methods that we want to use, we would then move on to what I will refer to as “helper methods”.

Helper methods are exactly what they sound like. Helper methods bridge the gap between the models and their methods shown above, and the CLI. They take information from the CLI and use that to perform the tasks desired. Following the get_all example above, we can see here a helper method being used to call the method and then iterate through to produce something, in this case a print statement. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ech8rx2nhihpjnegil0d.png)

This will be the building block of creating the CLI because much of the information displayed from these methods will become the options you choose. With that, let’s talk about the CLI.

CLI’s are generally pretty easy to grasp. You display a couple of numbered options, allow the user to input a number corresponding to whatever they want to choose, use a bunch of if statements and continue that trend. But, what if I want the CLI to display the owners from the example above and be able to choose any of those to display additional information or interact with the chosen user? The latter of that is the most important. When you are logged into an account on a website, you want to be able to only see information that is prevalent to you. I don’t want to see the recommended youtube feed from anybody else except what has been tailored to me. With a more serious example, I don’t want a user to be able to access any personal information of another user. All of this is checked and done by the backend. You want to make sure that any edits or private information is shown only to the selected user. We can do this fairly simply and it is shown in the example above. Enumerate is your friend. Enumerate will allow you to print a list of the users beginning at the number one and going until the list reaches the end. From there, you can select which user you want to focus on and move from there. It gets a little bit tricky when you try to access any of those owners along with additional options like adding a new one or backing out of that menu. This is solved by making sure your if statements are in correct order. In my own project, I have structured it so which works for me. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dz7cknnizdfjwzle3dcr.png)

We see at the top a while loop guaranteeing that we stay in this menu until the value of second_choice changes out of 1. From there we move down to the owners being listed through an enumerated iteration and then two additional options listed, add and move back. I create another while loop which serves as essentially the back button. The first if statement I added is exactly that. If the user inputs number equal to the list of owners plus 2, it will print that statement and set second_choice to 0, breaking the user out of that menu and moving up. The create owner does the same thing only after making sure a new user is created. After both of those is where I have added the if statement dealing with the list of owners. Here, I used an elif (else if) statement for a range of 1 to the len of owners + 1 to make sure all options can be selected. Whichever one gets selected there becomes the chosen_owner and moves into another while loop from there. This structure can be replicated numerous times to create an easy to navigate CLI for any user. The finished product looks like this.

Owner menu

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjcs11euzlk1fewao4r5.png)


Austen has been selected

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9bh8a6jwmiuju8epsq88.png)


And we can select the first book to see more information or edit it.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1798bskkjqxg1c7awh1.png)


Simple and straightforward but making sure that the menus flow in a direction that allows the user to always know where they are and what they are editing. Happy coding!