🐍 Python Beginner Course

Build a Python CMD Car Rental System 🚗

Master Python CRUD operations step-by-step — and discover how this simple project is the launchpad to full-stack web development with Django.

🟢 Beginner Level ⏱️ ~60 Minutes 💻 No Libraries Needed 🌍 Works on Windows / Mac / Linux
🚀
This is the starting point of your Full-Stack journey!

Python CMD → Python + File Storage → Django Web App → Django + MySQL → REST API → Full-Stack Developer 🎯 Mastering CRUD in the terminal is the foundation that every full-stack developer must understand first.

📘 Table of Contents

🎯 Introduction — Why Build This Project?

Welcome to one of the most practical beginner Python tutorials you will find! 🎉 In this complete guide, you will build a command-line Car Rental System using pure Python — no external libraries, no complicated setup. Just Python and your terminal.

But this tutorial is about more than just a Car Rental app. Every line of code you write here directly teaches you a skill that applies to real-world full-stack development. When you later build Django web apps, REST APIs, or database-powered systems, you will look back at this project and realise it taught you everything that matters:

📦
Data Structures

Lists and dictionaries — the same concept as database tables and rows.

🔁
Control Flow

Loops and conditionals that power every application ever built.

⚙️
Functions

Reusable code blocks — identical in concept to Django views.

🛠️
CRUD Operations

Create, Read, Update, Delete — the backbone of every app and API.

💬
User Input Handling

Processing input — mirrors handling web forms and API requests.

🧩
Modular Design

Splitting code into small functions — the foundation of clean architecture.

💡 Sri Lankan Developer Tip: Many IT companies in Colombo — and remote companies hiring globally — look for developers who understand CRUD at a fundamental level. Whether it's a PHP backend, a Django API, or a Laravel system, CRUD is the same concept everywhere. Nail it here in Python, and you'll understand it everywhere.

📖 What Exactly Is CRUD?

CRUD is an acronym that describes the four essential operations any data management system must support. It is not a Python-specific concept — it applies equally to MySQL databases, REST APIs, Django ORM, Firebase, Excel spreadsheets, and even paper filing systems! 😄

Letter Operation In Our App In Django/Web Apps In SQL
C Create Add a new car to the list POST request / form submit INSERT INTO
R Read Display all cars GET request / list view SELECT * FROM
U Update Edit car details PUT / PATCH request UPDATE SET
D Delete Remove a car DELETE request DELETE FROM

By completing this tutorial, you will have personally implemented all four CRUD operations in Python. That understanding transfers directly to any framework or language you use in the future. 🔥

🛠️ Prerequisites & Setup

Before you start coding, make sure you have the following ready. Don't worry — the setup takes less than 5 minutes!

✅ What You Need

🚀 Quick Installation Check

Open your terminal and type this to confirm Python is installed:

python --version
# or on some systems:
python3 --version

# You should see something like:
# Python 3.11.4

📁 Create Your Project File

Create a new folder and file to keep your work organised:

# Create a folder
mkdir car-rental
cd car-rental

# Create the Python file
# On Windows:
type nul > car_rental.py

# On Mac/Linux:
touch car_rental.py
ℹ️ VS Code Shortcut: Open your folder in VS Code with code . and you can write code and run it in the integrated terminal side by side. Highly recommended for beginners!

📋 Project Overview

Here is what our completed Car Rental System will be able to do. When a user runs the program, they will see a text-based menu with the following options:

==== Car Rental System ====
1. Add Car
2. View Cars
3. Update Car
4. Delete Car
5. Rent a Car
6. Return a Car
7. Exit

Enter choice:

Each option maps to a specific function in our code. Here is a quick summary of what each feature does:

Menu OptionFunctionCRUD TypeWhat It Does
1. Add Caradd_car()CREATETakes input and adds a car to the list
2. View Carsview_cars()READDisplays all cars with status
3. Update Carupdate_car()UPDATEEdits an existing car's details
4. Delete Cardelete_car()DELETERemoves a car from the list
5. Rent Carrent_car()UPDATEMarks a car as rented
6. Return Carreturn_car()UPDATEMarks a car as available again

1 Data Structure — The Heart of Your App

In Python, we store our car data in a list of dictionaries. Before we write a single function, we need to understand this data structure clearly — because everything else depends on it.

Think of a list like a table in a spreadsheet. Each dictionary inside the list is one row of data. Each key in the dictionary is a column header.

# Our car "database" — a Python list
cars = []

# What one car record looks like (a dictionary):
# {
#   "brand": "Toyota",
#   "model": "Corolla",
#   "price": 50.0,     # price per day
#   "rented": False    # is it currently rented?
# }
🔑 Key Concept — Dict as a DB Row: In Django, each database model instance is essentially a Python dictionary. When you do Car.objects.create(brand="Toyota") in Django, it's doing the exact same concept as cars.append({...}) here — just saving it to a real database instead. The logic is identical!

Understanding the Dictionary Fields

2 Add a Car — CREATE Operation

The CREATE operation is all about taking new data from the user and storing it. Our add_car() function uses Python's built-in input() function to collect the car details, builds a dictionary, and appends it to the cars list.

def add_car():
    print("\n-- Add New Car --")

    # Collect user input
    brand = input("Car Brand: ")
    model = input("Car Model: ")
    year  = input("Year of Manufacture: ")

    # Keep asking until valid price is entered
    while True:
        try:
            price = float(input("Rental Price Per Day ($): "))
            if price <= 0:
                print("⚠️  Price must be greater than zero. Try again.")
                continue
            break
        except ValueError:
            print("⚠️  Please enter a valid number.")

    # Build the car dictionary
    car = {
        "brand": brand,
        "model": model,
        "year":  year,
        "price": price,
        "rented": False
    }

    # Add to our list
    cars.append(car)
    print(f"\n✅ {brand} {model} added successfully!")
💡 What's New in This Version: We added input validation using a try/except block. This prevents your program from crashing if someone types letters instead of a number for the price. This is a real-world coding habit every developer must have!

🧠 How This Maps to Django (Full-Stack Preview)

In a Django web app, the equivalent of add_car() would be:

# Django equivalent — views.py
def add_car_view(request):
    if request.method == "POST":
        form = CarForm(request.POST)
        if form.is_valid():
            form.save()  # Same as cars.append(car) but saves to MySQL!
            return redirect("car_list")

See the parallels? The logic is the same — you are just collecting data and storing it. 🚀

3 View Cars — READ Operation

The READ operation retrieves stored data and displays it to the user. Our view_cars() function loops through every dictionary in the cars list and prints a formatted line for each one.

def view_cars():
    print("\n-- Available Cars --")

    if not cars:
        print("No cars available. Add some cars first! 🚗")
        return

    print(f"\n{'ID':<5} {'Brand':<12} {'Model':<15} {'Year':<6} {'Price/Day':<12} {'Status'}")
    print("-" * 60)

    for index, car in enumerate(cars):
        status = "🔴 Rented" if car["rented"] else "🟢 Available"
        print(
            f"{index:<5} {car['brand']:<12} {car['model']:<15} "
            f"{car.get('year','N/A'):<6} ${car['price']:<11.2f} {status}"
        )

    print("-" * 60)
    print(f"  Total cars: {len(cars)}")

We use Python's f-string formatting with alignment characters (< for left-align) to create a clean, table-like output in the terminal. The enumerate() function gives us both the index (ID) and the car dictionary in each loop iteration.

ℹ️ enumerate() Explained: for index, car in enumerate(cars) is the same as writing for i in range(len(cars)): but much cleaner. index gives you the position (0, 1, 2...) and car gives you the dictionary at that position.

4 Update a Car — UPDATE Operation

The UPDATE operation lets the user modify existing records. First we show the list so the user can pick the correct ID, then we update only the fields the user provides input for. If they leave a field blank, the old value is kept.

def update_car():
    view_cars()

    if not cars:
        return

    try:
        car_id = int(input("\nEnter Car ID to update: "))
        if car_id < 0 or car_id >= len(cars):
            print("❌ Invalid ID. Please enter a number from the list above.")
            return
    except ValueError:
        print("❌ Please enter a valid number.")
        return

    car = cars[car_id]
    print(f"\nUpdating: {car['brand']} {car['model']} (leave blank to keep current value)\n")

    new_brand = input(f"  Brand [{car['brand']}]: ").strip()
    new_model = input(f"  Model [{car['model']}]: ").strip()
    new_price = input(f"  Price/Day [${car['price']}]: ").strip()
    new_year  = input(f"  Year [{car.get('year','N/A')}]: ").strip()

    # Only update fields where user entered something
    if new_brand: car["brand"] = new_brand
    if new_model: car["model"] = new_model
    if new_year:  car["year"]  = new_year
    if new_price:
        try:
            car["price"] = float(new_price)
        except ValueError:
            print("⚠️  Invalid price entered — keeping original value.")

    print(f"\n✅ Car updated successfully!")
💡 Pro Tip — Show Current Values: Notice how we display the current value in the prompt, e.g., Brand [Toyota]:. This is a UX (User Experience) pattern used in professional CLI tools. It saves users from having to remember the old value before editing.

5 Delete a Car — DELETE Operation

The DELETE operation permanently removes a record. We always add a confirmation prompt before deleting — a critical safety measure in any real-world application!

def delete_car():
    view_cars()

    if not cars:
        return

    try:
        car_id = int(input("\nEnter Car ID to delete: "))
        if car_id < 0 or car_id >= len(cars):
            print("❌ Invalid ID.")
            return
    except ValueError:
        print("❌ Please enter a valid number.")
        return

    car = cars[car_id]

    # ⚠️ Always confirm before deleting!
    confirm = input(f"\n⚠️  Are you sure you want to delete {car['brand']} {car['model']}? (yes/no): ")

    if confirm.lower() == "yes":
        cars.pop(car_id)
        print("✅ Car deleted successfully!")
    else:
        print("❌ Deletion cancelled.")
⚠️ Golden Rule of DELETE: Always confirm before deleting. Always. In a web app, this means a confirmation dialog or a confirmation page. In a CLI app, it's a yes/no prompt. Skipping this is how developers accidentally delete important data!

6 Rent & Return — Business Logic Layer

Real applications have business logic — actions that go beyond basic CRUD and implement actual business rules. In our Car Rental System, the ability to rent and return cars is the core feature. These are essentially special UPDATE operations that change the rented status field.

def rent_car():
    """Mark a car as rented."""
    view_cars()

    if not cars:
        return

    try:
        car_id = int(input("\nEnter Car ID to rent: "))
        if car_id < 0 or car_id >= len(cars):
            print("❌ Invalid ID.")
            return
    except ValueError:
        print("❌ Please enter a valid number.")
        return

    car = cars[car_id]

    if car["rented"]:
        print(f"❌ Sorry! {car['brand']} {car['model']} is already rented.")
    else:
        days = int(input("How many days do you want to rent? "))
        total_cost = car["price"] * days
        car["rented"] = True
        print(f"\n✅ {car['brand']} {car['model']} rented for {days} days.")
        print(f"   💰 Total Cost: ${total_cost:.2f}")


def return_car():
    """Mark a car as returned (available)."""
    view_cars()

    if not cars:
        return

    try:
        car_id = int(input("\nEnter Car ID to return: "))
        if car_id < 0 or car_id >= len(cars):
            print("❌ Invalid ID.")
            return
    except ValueError:
        print("❌ Please enter a valid number.")
        return

    car = cars[car_id]

    if not car["rented"]:
        print(f"❌ {car['brand']} {car['model']} is not currently rented.")
    else:
        car["rented"] = False
        print(f"✅ {car['brand']} {car['model']} has been returned. Now available!")
🏆 Why This Matters for Full-Stack Dev: Business logic functions like rent_car() become service layer methods or Django model methods in a real web app. The logic is the same — you are validating state (is it already rented?) and performing a conditional update. Every web app you ever build will have this kind of business logic.

7 Main Menu Loop — The Application Controller

The menu function is the controller of our application. It runs in an infinite while True loop, continuously presenting options to the user and calling the appropriate function based on their input. The loop only exits when the user chooses option 7.

def menu():
    """Main application loop."""
    print("\n" + "="*40)
    print("    🚗 Welcome to Car Rental System 🚗")
    print("="*40)

    while True:
        print("\n──── Main Menu ────")
        print(" 1️⃣  Add Car")
        print(" 2️⃣  View Cars")
        print(" 3️⃣  Update Car")
        print(" 4️⃣  Delete Car")
        print(" 5️⃣  Rent a Car")
        print(" 6️⃣  Return a Car")
        print(" 7️⃣  Exit")
        print("───────────────────")

        choice = input("Enter your choice (1-7): ").strip()

        if   choice == "1": add_car()
        elif choice == "2": view_cars()
        elif choice == "3": update_car()
        elif choice == "4": delete_car()
        elif choice == "5": rent_car()
        elif choice == "6": return_car()
        elif choice == "7":
            print("\n👋 Thank you for using Car Rental System. Goodbye!")
            break
        else:
            print("❌ Invalid option. Please enter a number between 1 and 7.")


# ── Entry Point ──
if __name__ == "__main__":
    menu()
ℹ️ if __name__ == "__main__": Explained: This line is a Python best practice. It ensures the menu() function only runs when you directly execute the file. If another Python file imports this file as a module, menu() won't automatically run. This is important for building larger, modular projects.

🎉 Final Complete Program

Here is the entire Car Rental System in one file. You can copy this, save it as car_rental.py, and run it with python car_rental.py in your terminal!

# ============================================================
#  🚗 Python Car Rental System — EgoTECH World
#  Complete CRUD Command-Line Application
#  Perfect starter project for full-stack beginners
#  egotechworld.com
# ============================================================

cars = []  # Our in-memory "database"


# ── CREATE ──────────────────────────────────────────────────
def add_car():
    print("\n-- Add New Car --")
    brand = input("Car Brand: ").strip()
    model = input("Car Model: ").strip()
    year  = input("Year of Manufacture: ").strip()

    while True:
        try:
            price = float(input("Rental Price Per Day ($): "))
            if price <= 0:
                print("⚠️  Price must be positive.")
                continue
            break
        except ValueError:
            print("⚠️  Invalid price. Enter a number.")

    cars.append({
        "brand": brand,
        "model": model,
        "year":  year,
        "price": price,
        "rented": False
    })
    print(f"\n✅ {brand} {model} added successfully!")


# ── READ ─────────────────────────────────────────────────────
def view_cars():
    print("\n-- Car List --")
    if not cars:
        print("No cars found. Add some cars first! 🚗")
        return

    print(f"\n{'ID':<5} {'Brand':<12} {'Model':<15} {'Year':<6} {'Price/Day':<12} {'Status'}")
    print("-" * 62)
    for i, car in enumerate(cars):
        status = "🔴 Rented" if car["rented"] else "🟢 Available"
        print(f"{i:<5} {car['brand']:<12} {car['model']:<15} {car.get('year','N/A'):<6} ${car['price']:<11.2f} {status}")
    print("-" * 62)
    print(f"  Total: {len(cars)} car(s)")


# ── UPDATE ───────────────────────────────────────────────────
def update_car():
    view_cars()
    if not cars:
        return
    try:
        cid = int(input("\nCar ID to update: "))
        assert 0 <= cid < len(cars)
    except (ValueError, AssertionError):
        print("❌ Invalid ID.")
        return

    car = cars[cid]
    print(f"\nUpdating {car['brand']} {car['model']} (blank = keep current)\n")

    b = input(f"  Brand [{car['brand']}]: ").strip()
    m = input(f"  Model [{car['model']}]: ").strip()
    y = input(f"  Year  [{car.get('year','N/A')}]: ").strip()
    p = input(f"  Price [${car['price']}]: ").strip()

    if b: car["brand"] = b
    if m: car["model"] = m
    if y: car["year"]  = y
    if p:
        try:
            car["price"] = float(p)
        except ValueError:
            print("⚠️  Invalid price — keeping original.")

    print("✅ Car updated!")


# ── DELETE ───────────────────────────────────────────────────
def delete_car():
    view_cars()
    if not cars:
        return
    try:
        cid = int(input("\nCar ID to delete: "))
        assert 0 <= cid < len(cars)
    except (ValueError, AssertionError):
        print("❌ Invalid ID.")
        return

    car = cars[cid]
    if input(f"⚠️  Delete {car['brand']} {car['model']}? (yes/no): ").lower() == "yes":
        cars.pop(cid)
        print("✅ Car deleted!")
    else:
        print("❌ Cancelled.")


# ── RENT ─────────────────────────────────────────────────────
def rent_car():
    view_cars()
    if not cars:
        return
    try:
        cid = int(input("\nCar ID to rent: "))
        assert 0 <= cid < len(cars)
    except (ValueError, AssertionError):
        print("❌ Invalid ID.")
        return

    car = cars[cid]
    if car["rented"]:
        print(f"❌ {car['brand']} {car['model']} is already rented!")
    else:
        try:
            days = int(input("Number of days: "))
            cost = car["price"] * days
            car["rented"] = True
            print(f"✅ Rented for {days} day(s).  💰 Total: ${cost:.2f}")
        except ValueError:
            print("❌ Invalid input.")


# ── RETURN ───────────────────────────────────────────────────
def return_car():
    view_cars()
    if not cars:
        return
    try:
        cid = int(input("\nCar ID to return: "))
        assert 0 <= cid < len(cars)
    except (ValueError, AssertionError):
        print("❌ Invalid ID.")
        return

    car = cars[cid]
    if not car["rented"]:
        print(f"❌ {car['brand']} {car['model']} is not rented.")
    else:
        car["rented"] = False
        print(f"✅ {car['brand']} {car['model']} returned. Now available!")


# ── MENU ─────────────────────────────────────────────────────
def menu():
    print("\n" + "="*42)
    print("    🚗 Car Rental System — EgoTECH World")
    print("="*42)

    while True:
        print("\n──── Main Menu ────")
        print(" 1  Add Car        (CREATE)")
        print(" 2  View Cars      (READ)")
        print(" 3  Update Car     (UPDATE)")
        print(" 4  Delete Car     (DELETE)")
        print(" 5  Rent a Car")
        print(" 6  Return a Car")
        print(" 7  Exit")
        print("───────────────────")

        choice = input("Choice (1-7): ").strip()

        if   choice == "1": add_car()
        elif choice == "2": view_cars()
        elif choice == "3": update_car()
        elif choice == "4": delete_car()
        elif choice == "5": rent_car()
        elif choice == "6": return_car()
        elif choice == "7":
            print("\n👋 Goodbye! Keep coding! 🚀")
            break
        else:
            print("❌ Enter a number from 1 to 7.")


if __name__ == "__main__":
    menu()

🎬 Watch: Python for Beginners — Full Tutorial

Prefer learning by watching? This video covers Python fundamentals including functions, lists, dictionaries, loops, and user input — everything you need to fully understand this project. Watch it alongside this tutorial!

🎓 Recommended: Python for Beginners — covers all the concepts used in this project. Watch at 1.25x speed once you understand the basics!

🧪 How to Test Your Application

Once you have the code saved as car_rental.py, here's a step-by-step test workflow:

  1. Run the program:
    python car_rental.py
  2. Add 3 cars (option 1) — try Toyota Corolla, Honda Civic, BMW X5
  3. View all cars (option 2) — confirm all 3 appear with "Available" status
  4. Rent car #0 (option 5) — enter 3 days, check the cost is correct
  5. View cars again (option 2) — confirm car #0 now shows "Rented"
  6. Update car #1 (option 3) — change only the price, leave other fields blank
  7. Delete car #2 (option 4) — confirm by typing "yes"
  8. Return car #0 (option 6) — confirm it shows "Available" again
  9. View final list (option 2) — should have 2 cars, both available
  10. Exit (option 7)
⚠️ Important Limitation to Know: In this version, data is stored in memory only. When you close the program, all car data is lost. This is intentional — it keeps the focus on learning CRUD logic without the complexity of file I/O or databases. In the next level of this course, we will save data to a JSON file. After that, we move to a real database with Django. 🔥

🛠️ How to Extend This Project

Once you are comfortable with the basic version, here are challenges you can try yourself. Each one teaches you a new skill:

🥉 Beginner Challenge

Add a Search Feature

Write a search_cars(brand) function that loops through the list and prints only matching cars. Practice: loops + string comparison.

🥉 Beginner Challenge

Count Rented vs Available

Add a summary line to view_cars() showing how many cars are rented and how many are available. Practice: conditional counting.

🥈 Intermediate Challenge

Save Data to JSON File

Use Python's json module to save and load the cars list from a file. Your data will now persist between runs! Practice: file I/O.

🥈 Intermediate Challenge

Add a Customer System

Create a second list: customers = []. Track which customer rented which car. Practice: relationships between data — exactly like foreign keys in SQL!

🥇 Advanced Challenge

Migrate to SQLite

Replace the list with an SQLite database using Python's built-in sqlite3 module. Now your CRUD operations use real SQL queries. Practice: databases!

🏆 Full-Stack Challenge

Build the Django Version

Rebuild this entire system as a Django web application with HTML pages, forms, and MySQL. This is the full-stack milestone! Follow our Django courses on EgoTECH. 🚀

🚀 Your Full-Stack Python Developer Path

This project is Step 1 of a carefully designed learning journey. Here is the complete path from absolute beginner to full-stack Python developer — and you are already on it! 🎉

1
Python Basics + CMD CRUD ← YOU ARE HERE ✅

Functions, loops, dictionaries, user input, CRUD operations, input validation. This project.

2
Python + File Storage (JSON / CSV)

Persist your data using JSON files. Learn file reading/writing, data serialisation. Same car rental system — now it remembers data!

3
Python + SQLite Database

Replace JSON with a real relational database. Write actual SQL INSERT, SELECT, UPDATE, DELETE queries from Python. Huge milestone!

4
Django Basics — Your First Web App

Learn Django's MVT architecture. Create models, views, templates, URLs. Rebuild the car rental as a real webpage. HTML forms instead of input()!

5
Django + MySQL + User Auth

Connect your Django app to MySQL, add user login/registration, role-based permissions. This is production-level back-end development!

6
Django REST Framework — API Development

Build JSON APIs that mobile apps and frontend frameworks can consume. The standard for modern full-stack Python development.

7
🏆 Full-Stack Developer — Deployed, Live Project

Deploy on VPS/cloud, add HTTPS, CI/CD. You have built, tested, and shipped a complete web application. You are a full-stack developer! 🎓

🎓 EgoTECH World Full-Stack Python Courses: We are building a complete Sinhala-language course series covering every step of this path — from Python basics all the way to Django REST API deployment. 👉 Check our Courses page to follow the journey!

❓ Frequently Asked Questions

No! This project uses zero external libraries. Everything is built with Python's built-in features: lists, dictionaries, functions, loops, input(), and print(). Just install Python and you are ready to go.

Because we store data in a Python list (cars = []) which lives in your computer's RAM (temporary memory). When the program closes, RAM is cleared. To persist data, you need either a JSON file (beginner approach) or a database like SQLite or MySQL (the professional approach). This is covered in our next course modules.

CRUD is the concept (Create, Read, Update, Delete). A REST API is a way of delivering CRUD operations over HTTP. In a REST API: Create = POST, Read = GET, Update = PUT/PATCH, Delete = DELETE. Our command-line app delivers the same CRUD operations via keyboard input instead of HTTP. Same logic, different delivery method!

Absolutely! Python and Django skills are in growing demand in Colombo's tech scene — companies like 99X, WSO2, Virtusa, and many startups use Python backends. More importantly, Python opens doors to international remote work (Upwork, Toptal, direct contracts) which can earn you USD income from Sri Lanka. Django + REST API skills are especially valued. Start here, build your portfolio, and check our Jobs board for current local IT opportunities!

With consistent daily practice (1-2 hours/day), most beginners can build their first Django CRUD web app within 4-8 weeks after completing this Python basics phase. The secret: you already understand CRUD logic from this project. Django just gives you better tools to do the same thing with a web interface. Follow the EgoTECH full-stack path and we will guide you every step of the way!
📚 Continue Learning on EgoTECH World