wormondeck
Posted on October 2, 2024
Opening Credits
The second it all clicks, consider the project fun. I built a client friendly CLI project to grasp how a class, methods, and properties work.
My directory structure was quite simple:
└── lib
├── models
│ ├── __init__.py
│ └── actor.py
| └── movie.py
├── cli.py
├── debug.py
└── helpers.py
├── Pipfile
├── Pipfile.lock
├── README.md
As you can see from the structure I built a one-to-many association where an actor has many movies. From this association my menu came into play.
- Current list of actors
- Add an Actor
- Delete an Actor
- Exit the program
My menu above was defined by a function called... menu()
which was located in my cli.py
file along with the main()
which shows the user the CLI menu:
def main():
while True:
welcome()
menu()
choice = input("> ").strip()
if choice == "1":
actor_list()
elif choice == "2":
add_actor()
elif choice == "3":
delete_actor()
elif choice == "4":
exit_program()
break
else:
print("Invalid choice. Try again.\n")
This particular function was the first of many where a while loop along with if/elif/else statements were executed to give our user the ability to navigate our menus with ease.
The cli.py
is then concluded with some important code block:
if __name__ == "__main__":
main()
This code block tells our interpreter (Python) to only run our file if it is called from the command line.
Supporting Cast
There were also helper functions involved in this project which also used a while loop along with if/elif/else statements. One in particular stands out in showing ease of navigation when selecting for example our current list of actors:
def actor_list():
actor_list = Actor.get_all()
if actor_list:
print("\n*** UPDATED LIST! ***")
for i, actor in enumerate(actor_list, start=1):
print(f"{i}. {actor.name}")
while True:
choice = input("Press 'a' to add an actor\n"
"Press 'b' for actor profile\n"
"Press 'c' to return to the main menu.\n"
"Press 'd' delete an actor.\n").lower()
if choice == 'a':
add_actor()
break
elif choice == 'b':
actor_profile()
break
elif choice == 'c':
return
elif choice == 'd':
delete_actor()
break
else:
print("Invalid choice. Please try again.")
else:
print("List empty!")
while True:
choice = input("Press 'a' or to add an actor\n"
"Press 'b' for main menu.\n").lower()
if choice == 'a':
add_actor()
break
elif choice == 'b':
return
else:
print("Invalid choice. Please try again.")
Here not only did I became accustomed of the while loop and if statements but also reap the benefits of appearance and order by using enumerate() with a for loop to iterate with an index in python allowing all the lists thru out the project to be an ordered list.
Show Some Class
Our two main characters of course are the Classes Actor and Movie. Both consist of similar code in terms of class methods when creating, updating or deleting an instance of that particular class, but there are differences:
Let's take our Movie class for example:
class Movie:
all_movies = {}
def __init__(self, movie, genre, actor_id, id=None):
self.id = id
self.movie = movie
self.genre = genre
self.actor_id = actor_id
Since we have our project setup where an actor has many movies, our movie class will have a unique actor_id
parameter/attribute to establish a link between the movie instance and a specific actor, allowing easy reference to the actor's information.
Now look at this code block in our Actor class:
def movies(self):
from models.movie import Movie
sql = """
SELECT * FROM movie
WHERE actor_id = ?
"""
CURSOR.execute(sql, (self.id,),)
rows = CURSOR.fetchall()
return [
Movie.instance_from_db(row) for row in rows
]
Here we have our movies() method retrieve all the movies associated with the current Actor instance by querying the movie table using the actor's ID. This will then return a list of Movie objects, establishing a "has-many" relationship between Actor and Movie.
The code blocks discussed were the primary areas of the project where I focused on grasping more understanding. Overall this project served as a good exercise to enhance my skills in python.
Posted on October 2, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.