DEV Community

Cover image for Day 63 of #100DaysOfCode — Python Refresher Part 3 + Introduction to Apps in Django
M Saad Ahmad
M Saad Ahmad

Posted on

Day 63 of #100DaysOfCode — Python Refresher Part 3 + Introduction to Apps in Django

Yesterday I introduced Django and covered some Python basics. Today I went deeper into Python, specifically functions and OOP, because I realized these are the real building blocks you need before Django starts making sense. I also took a first look at how Django organizes code into apps.


Functions in Python

A function in Python is defined using the def keyword.

def greet(name):
    return f"Hello, {name}!"

print(greet("Haris"))  # Hello, Haris!
Enter fullscreen mode Exit fullscreen mode

Simple enough. But Python functions have some powerful features worth knowing.


Default Arguments

You can assign a default value to parameters, making them optional when calling the function.

def greet(name, greeting="Hello"):
    return f"{greeting}, {name}!"

print(greet("Haris"))           # Hello, Haris!
print(greet("Haris", "Hey"))    # Hey, Haris!
Enter fullscreen mode Exit fullscreen mode

*args: Variable Positional Arguments

When you don't know how many arguments will be passed, use *args. It collects all extra positional arguments into a tuple.

def add_all(*args):
    return sum(args)

print(add_all(1, 2, 3))       # 6
print(add_all(10, 20, 30, 40)) # 100
Enter fullscreen mode Exit fullscreen mode

**kwargs: Variable Keyword Arguments

**kwargs collects extra keyword arguments into a dictionary.

def display_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

display_info(name="Haris", role="Developer", day=63)
# name: Haris
# role: Developer
# day: 63
Enter fullscreen mode Exit fullscreen mode

Combining them all

You can use all of these together. The order matters: regular args → *args → **kwargs.

def mixed(name, *args, **kwargs):
    print(f"Name: {name}")
    print(f"Extra values: {args}")
    print(f"Extra info: {kwargs}")

mixed("Haris", 1, 2, 3, role="Dev", day=63)
# Name: Haris
# Extra values: (1, 2, 3)
# Extra info: {'role': 'Dev', 'day': 63}
Enter fullscreen mode Exit fullscreen mode

Lambda Functions

Lambda is a way to write a small, single-expression function in one line.

square = lambda x: x ** 2
print(square(5))  # 25
Enter fullscreen mode Exit fullscreen mode

Useful when passing simple functions as arguments, like in sorted() or map().

names = ["Haris", "Ali", "Zara"]
sorted_names = sorted(names, key=lambda x: len(x))
print(sorted_names)  # ['Ali', 'Zara', 'Haris']
Enter fullscreen mode Exit fullscreen mode

OOP in Python

Python is fully object-oriented. Here's how the core concepts translate.


Classes and __init__

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def introduce(self):
        return f"Hi, I'm {self.name} and I'm {self.age} years old."

p = Person("Haris", 22)
print(p.introduce())  # Hi, I'm Haris, and I'm 22 years old.
Enter fullscreen mode Exit fullscreen mode

__init__ is the constructor. self refers to the current instance — similar to this in JavaScript or C++.


Inheritance

class Developer(Person):
    def __init__(self, name, age, language):
        super().__init__(name, age)
        self.language = language

    def introduce(self):
        return f"Hi, I'm {self.name}, I code in {self.language}."

dev = Developer("Haris", 22, "Python")
print(dev.introduce())  # Hi, I'm Haris, I code in Python.
Enter fullscreen mode Exit fullscreen mode

super() calls the parent class constructor; same concept as in C++ or JavaScript.


Class vs Instance Attributes

class Counter:
    count = 0  # class attribute, shared across all instances

    def __init__(self, name):
        self.name = name  # instance attribute, unique per instance
        Counter.count += 1

c1 = Counter("First")
c2 = Counter("Second")
print(Counter.count)  # 2
Enter fullscreen mode Exit fullscreen mode

Dunder (Magic) Methods

Python uses special __methods__ to define how objects behave with built-in operations.

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"Point({self.x}, {self.y})"

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1 + p2)   # Point(4, 6)
print(p1)        # Point(1, 2)
Enter fullscreen mode Exit fullscreen mode

These are heavily used in Django's model system under the hood.


Introduction to Apps in Django

Now, a quick look at how Django structures your project.

In Django, a project is the entire web application. But inside it, you organize functionality into smaller units called apps. Each app handles one specific part of your project.

For example, a blog website might have:

  • a posts app — handles blog posts
  • a users app — handles authentication
  • a comments app — handles comments

This keeps your code modular and clean.


Creating an App

python manage.py startapp posts
Enter fullscreen mode Exit fullscreen mode

This creates a folder called posts with this structure:

posts/
    migrations/
    __init__.py
    admin.py
    apps.py
    models.py
    tests.py
    views.py
Enter fullscreen mode Exit fullscreen mode

Each file has a role:

  • models.py — define your database structure
  • views.py — handle request/response logic
  • admin.py — register models with Django admin

Registering the App

After creating an app, you register it in settings.py:

INSTALLED_APPS = [
    ...
    'posts',
]
Enter fullscreen mode Exit fullscreen mode

Without this, Django doesn't know the app exists.


Wrapping Up

Today felt like filling in the real gaps: functions with *args and **kwargs, OOP with classes and inheritance, and getting a first look at how Django apps are structured. These are the pieces that will actually matter once we start building real Django views and models.

Thanks for reading. Feel free to share your thoughts!

Top comments (0)