Chapter 4 of 12
Models are Python classes that define your data structure. Django reads these classes and automatically creates database tables โ you never write SQL to create tables.
# courses/models.py
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
class Meta:
verbose_name_plural = "categories"
def __str__(self):
return self.name # shown in admin and shell
class Course(models.Model):
LEVEL_CHOICES = [
("beginner", "Beginner"),
("intermediate", "Intermediate"),
("advanced", "Advanced"),
]
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
description = models.TextField(blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="courses")
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
level = models.CharField(max_length=20, choices=LEVEL_CHOICES, default="beginner")
is_live = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return self.title# Create migration files (based on changes to models.py)
python manage.py makemigrations
# Apply migrations โ actually create/alter the database tables
python manage.py migrate
# See all migrations
python manage.py showmigrations
# Every time you change models.py:
# 1. python manage.py makemigrations
# 2. python manage.py migrate# String fields
models.CharField(max_length=200) # short text, max_length required
models.TextField() # long text, no limit
models.SlugField() # URL-friendly string
# Number fields
models.IntegerField()
models.FloatField()
models.DecimalField(max_digits=10, decimal_places=2)
# Boolean and null
models.BooleanField(default=False)
models.NullBooleanField() # True / False / None
# Dates
models.DateField()
models.DateTimeField()
models.DateTimeField(auto_now_add=True) # set on create
models.DateTimeField(auto_now=True) # set on every save
# Files
models.ImageField(upload_to="covers/")
models.FileField(upload_to="uploads/")
# Relationships
models.ForeignKey(Category, on_delete=models.CASCADE) # many-to-one
models.ManyToManyField(Tag) # many-to-many
models.OneToOneField(User, on_delete=models.CASCADE) # one-to-one