Python Notes
HubHistory of Python - Complete Guide 2026Python Applications - Complete Guide 2026Python Features - Complete Guide 2026What is Python? - Complete Guide 2026Why Learn Python? - Complete Guide 2026Your First Python Program – Hello World & Beyond 2026How to Install Python on Windows, Mac & Linux – Complete Guide 2026Install VS Code for Python – Complete Setup Guide with Extensions 2026Python Environment Setup – Virtual Environments, pip & Project Structure 2026Python IDLE – Complete Guide for Beginners 2026Python CommentsPython Data TypesPython Input and OutputPython OperatorsPython SyntaxPython Strings BasicsPython Type CastingPython VariablesBreak, Continue and Pass in PythonElif Statement in PythonFor Loop in PythonIf-Else Statement in PythonIf Statement in PythonNested If in PythonPattern Programs in PythonWhile Loop in PythonDecorators in PythonFunction Arguments in PythonFunctions Basics in PythonGenerators in PythonLambda Functions in PythonRecursive Functions in PythonReturn Statement in PythonScope of Variables in PythonAbstraction in PythonClasses and Objects in PythonConstructors in PythonEncapsulation in PythonInheritance in PythonMagic Methods (Dunder Methods) in PythonMethod Overriding in PythonPolymorphism in PythonPython Comprehensions – List, Dict, Set & GeneratorPython Dictionaries – Key-Value StorePython Dictionary Methods – Complete ReferencePython List Methods – All Built-in MethodsPython Lists – Complete GuidePython Set Methods – Complete ReferencePython Sets – Unordered Unique CollectionsPython Tuples – Immutable SequencesPython Asynchronous Programming with asyncioPython Context ManagersAdvanced Python DecoratorsAdvanced Python GeneratorsPython Iterators - Advanced GuidePython Memory ManagementPython MultiprocessingPython MultithreadingCRUD Operations in Python DatabasesMySQL with Python (mysql-connector-python)ORM Introduction with SQLAlchemyPostgreSQL with Python (psycopg2)SQLite3 with PythonIntroduction to DjangoDjango Models and ORMDjango REST API with DRFDjango ViewsIntroduction to FlaskFlask RoutingFlask Templates with Jinja2Email Automation with PythonPDF Automation with PythonSelenium Web Automation with PythonTask Scheduler with PythonWeb Scraping with PythonData Analysis with PythonData Cleaning with PythonData Visualization ProjectData Visualization with MatplotlibNumPy IntroductionPandas IntroductionStatistical Visualization with SeabornClassification AlgorithmsClustering AlgorithmsIntroduction to Machine LearningMachine Learning Project: Churn PredictionModel Evaluation and SelectionRegression AlgorithmsSave pipeline (includes preprocessing + model)AI Assistant ProjectCalculator ProjectChatbot ProjectExpense Tracker ProjectFace Detection ProjectPassword Generator ProjectWeather App ProjectPython Coding Interview QuestionsPython OOP Interview Questions and AnswersPython Master CheatsheetPython Interview Questions and AnswersPython Best PracticesCommon Python Errors and SolutionsPython Debugging TechniquesPython Learning Resources
Master Django models and the ORM. Learn to define database models, field types, relationships (ForeignKey, ManyToMany, OneToOne), migrations, QuerySets, and advanced database queries in Django.
Django models are Python classes that define the structure of your database tables. The Django ORM (Object-Relational Mapper) lets you interact with databases using Python instead of SQL.
Defining Models
Example
# blog/models.py
from django.db import models
from django.contrib.auth.models import User
from django.utils.text import slugify
from django.urls import reverse
class Tag(models.Model):
name = models.CharField(max_length=50, unique=True)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
def __str__(self):
return self.name
class Category(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
description = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = 'categories'
ordering = ['name']
class Post(models.Model):
STATUS_DRAFT = 'draft'
STATUS_PUBLISHED = 'published'
STATUS_CHOICES = [
(STATUS_DRAFT, 'Draft'),
(STATUS_PUBLISHED, 'Published'),
]
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
tags = models.ManyToManyField(Tag, blank=True)
content = models.TextField()
excerpt = models.TextField(max_length=500, blank=True)
featured_image = models.ImageField(upload_to='posts/%Y/%m/', blank=True, null=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default=STATUS_DRAFT)
views_count = models.PositiveIntegerField(default=0)
is_featured = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
published_at = models.DateTimeField(null=True, blank=True)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['-created_at']),
models.Index(fields=['status', '-published_at']),
]
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post-detail', kwargs={'slug': self.slug})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
@property
def is_published(self):
return self.status == self.STATUS_PUBLISHED
def increment_views(self):
self.views_count += 1
self.save(update_fields=['views_count'])
Field Types
Django provides many built-in field types:
Example
from django.db import models
class ProductExample(models.Model):
# Text Fields
name = models.CharField(max_length=200) # Short text (VARCHAR)
description = models.TextField() # Long text
slug = models.SlugField(max_length=200) # URL-friendly text
email = models.EmailField() # Email validation
url = models.URLField() # URL validation
uuid = models.UUIDField() # UUID field
# Numeric Fields
price = models.DecimalField(max_digits=10, decimal_places=2)
quantity = models.IntegerField(default=0)
stock = models.PositiveIntegerField(default=0)
rating = models.FloatField(default=0.0)
# Boolean Fields
is_active = models.BooleanField(default=True)
is_featured = models.BooleanField(default=False)
# Date/Time Fields
created_at = models.DateTimeField(auto_now_add=True) # Set on create
updated_at = models.DateTimeField(auto_now=True) # Set on every save
publish_date = models.DateField(null=True, blank=True)
sale_start = models.TimeField(null=True, blank=True)
duration = models.DurationField(null=True, blank=True)
# File Fields
image = models.ImageField(upload_to='products/')
document = models.FileField(upload_to='docs/')
# Choice Field
CATEGORY_CHOICES = [
('electronics', 'Electronics'),
('clothing', 'Clothing'),
('books', 'Books'),
('food', 'Food'),
]
category = models.CharField(max_length=20, choices=CATEGORY_CHOICES)
# JSON Field (Django 3.1+)
metadata = models.JSONField(default=dict, blank=True)
# IP Address
created_from_ip = models.GenericIPAddressField(null=True, blank=True)
Relationships
ForeignKey (Many-to-One)
python example
class Comment(models.Model):
post = models.ForeignKey(
Post,
on_delete=models.CASCADE, # Delete comments when post is deleted
related_name='comments' # Access via post.comments.all()
)
author = models.ForeignKey(
User,
on_delete=models.SET_NULL, # Set null when user is deleted
null=True,
related_name='comments'
)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'Comment by {self.author} on {self.post}'on_delete options:
CASCADE— Delete related objectsSET_NULL— Set to null (requiresnull=True)SET_DEFAULT— Set to default valuePROTECT— Prevent deletion if related objects existDO_NOTHING— Do nothing (can cause integrity errors)
ManyToManyField
Example
class Article(models.Model):
title = models.CharField(max_length=200)
tags = models.ManyToManyField('Tag', blank=True)
# With intermediary table (through model)
liked_by = models.ManyToManyField(
User,
through='ArticleLike',
related_name='liked_articles',
blank=True
)
class ArticleLike(models.Model):
"""Intermediary table for likes with extra data."""
user = models.ForeignKey(User, on_delete=models.CASCADE)
article = models.ForeignKey(Article, on_delete=models.CASCADE)
liked_at = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = ['user', 'article']
OneToOneField
python example
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
bio = models.TextField(blank=True)
avatar = models.ImageField(upload_to='avatars/', blank=True, null=True)
website = models.URLField(blank=True)
location = models.CharField(max_length=100, blank=True)
birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return f'Profile of {self.user.username}'
def get_avatar_url(self):
if self.avatar:
return self.avatar.url
return '/static/images/default-avatar.png'Migrations
bash example
# Create migration files based on model changes
python manage.py makemigrations
# Make migrations for a specific app
python manage.py makemigrations blog
# Preview the SQL that will be run
python manage.py sqlmigrate blog 0001
# Apply migrations
python manage.py migrate
# Check migration status
python manage.py showmigrations
# Undo a migration (rollback)
python manage.py migrate blog 0001 # Revert to migration 0001
# Squash migrations (combine multiple into one)
python manage.py squashmigrations blog 0001 0005QuerySets — Retrieving Data
Example
from blog.models import Post, Category, Tag
# --- Basic Retrieval ---
# Get all objects
all_posts = Post.objects.all()
# Get with filter
published = Post.objects.filter(status='published')
featured = Post.objects.filter(is_featured=True, status='published')
# Get single object (raises DoesNotExist if not found)
post = Post.objects.get(id=1)
post = Post.objects.get(slug='my-first-post')
# Safe get with get_object_or_404 (in views)
from django.shortcuts import get_object_or_404
post = get_object_or_404(Post, slug='my-post')
# Get first / last
first_post = Post.objects.first()
latest_post = Post.objects.last()
# Count
total = Post.objects.count()
published_count = Post.objects.filter(status='published').count()
# Check existence
exists = Post.objects.filter(slug='test').exists()
# --- Filtering ---
# Exact match
Post.objects.filter(status='published')
# Case-insensitive contains
Post.objects.filter(title__icontains='python')
# Starts with / ends with
Post.objects.filter(title__startswith='How')
Post.objects.filter(title__endswith='?')
# Greater/Less than
Post.objects.filter(views_count__gt=100)
Post.objects.filter(views_count__gte=100)
Post.objects.filter(views_count__lt=10)
Post.objects.filter(views_count__lte=10)
# In a list
Post.objects.filter(status__in=['draft', 'published'])
# Not in
Post.objects.exclude(status='draft')
# Null checks
Post.objects.filter(published_at__isnull=True)
Post.objects.filter(featured_image__isnull=False)
# Date filtering
from django.utils import timezone
today = timezone.now().date()
Post.objects.filter(created_at__date=today)
Post.objects.filter(created_at__year=2026)
Post.objects.filter(created_at__month=6)
# Relationship filtering
Post.objects.filter(author__username='alice')
Post.objects.filter(category__name='Technology')
Post.objects.filter(tags__name='python') # Many-to-many
# --- Complex Queries with Q objects ---
from django.db.models import Q
# OR condition
Post.objects.filter(Q(status='published') | Q(is_featured=True))
# AND condition (same as chaining .filter())
Post.objects.filter(Q(status='published') & Q(author__username='alice'))
# NOT condition
Post.objects.filter(~Q(status='draft'))
# Complex combined
Post.objects.filter(
Q(status='published') | Q(is_featured=True),
~Q(author__username='banned_user')
)
QuerySets — Ordering and Slicing
Example
# Order by field
Post.objects.order_by('created_at') # Ascending
Post.objects.order_by('-created_at') # Descending
Post.objects.order_by('-created_at', 'title') # Multiple fields
# Random order
Post.objects.order_by('?')
# Slicing (like Python list slicing — returns QuerySet)
first_five = Post.objects.all()[:5]
posts_6_to_10 = Post.objects.all()[5:10]
latest_ten = Post.objects.order_by('-created_at')[:10]
# Specific field values only (flat list)
titles = Post.objects.values_list('title', flat=True) # ['Post 1', 'Post 2', ...]
ids = Post.objects.values_list('id', flat=True)
# Dictionary of fields
posts_data = Post.objects.values('id', 'title', 'author__username')
Aggregation and Annotation
python example
from django.db.models import Count, Sum, Avg, Max, Min, F, Value
from django.db.models.functions import Concat
# Aggregation — single result
from blog.models import Post
stats = Post.objects.aggregate(
total=Count('id'),
total_views=Sum('views_count'),
avg_views=Avg('views_count'),
max_views=Max('views_count'),
)
print(stats)
# {'total': 50, 'total_views': 12345, 'avg_views': 246.9, 'max_views': 3210}
# Annotation — adds computed field to each object
posts = Post.objects.annotate(
comment_count=Count('comments'),
total_likes=Count('liked_by')
)
for post in posts:
print(f'{post.title}: {post.comment_count} comments, {post.total_likes} likes')
# Group by (category post counts)
category_counts = Category.objects.annotate(
post_count=Count('post')
).order_by('-post_count')
# Using F expressions (reference another field)
Post.objects.filter(views_count__gt=F('comments') * 10)Optimizing Queries
python example
# select_related — for ForeignKey/OneToOne (SQL JOIN)
# Avoids N+1 query problem for single related objects
posts = Post.objects.select_related('author', 'category').filter(status='published')
# prefetch_related — for ManyToMany/reverse FK
# Separate query, cached in Python
posts = Post.objects.prefetch_related('tags', 'comments').all()
# Combine both
posts = Post.objects.select_related('author', 'category').prefetch_related('tags')
# Only fetch specific fields (faster for large models)
posts = Post.objects.only('id', 'title', 'slug', 'created_at')
# Defer specific fields (fetch everything except these)
posts = Post.objects.defer('content', 'metadata')
# Checking query count (debugging)
from django.test.utils import CaptureQueriesContext
from django.db import connection
with CaptureQueriesContext(connection) as queries:
list(Post.objects.select_related('author').all())
print(f'Query count: {len(queries)}')Creating, Updating, and Deleting
Example
# --- Create ---
# Method 1: create()
post = Post.objects.create(
title='My New Post',
content='Post content here...',
author=user,
status='published'
)
# Method 2: save()
post = Post(title='Another Post', content='...', author=user)
post.save()
# Method 3: get_or_create()
tag, created = Tag.objects.get_or_create(
name='Python',
defaults={'slug': 'python'}
)
if created:
print('New tag created')
else:
print('Tag already existed')
# Method 4: update_or_create()
obj, created = Post.objects.update_or_create(
slug='my-post',
defaults={'title': 'Updated Title', 'status': 'published'}
)
# --- Update ---
# Update single object
post = Post.objects.get(id=1)
post.title = 'Updated Title'
post.save()
# Update only specific fields (more efficient)
post.save(update_fields=['title', 'status'])
# Bulk update (single SQL query)
Post.objects.filter(status='draft').update(status='published')
# Using F() for atomic updates
from django.db.models import F
Post.objects.filter(id=1).update(views_count=F('views_count') + 1)
# --- Delete ---
post = Post.objects.get(id=1)
post.delete()
# Bulk delete
Post.objects.filter(status='draft', created_at__year=2024).delete()
# Delete all
Post.objects.all().delete() # ⚠️ Careful!
Custom Model Managers
Example
from django.db import models
class PublishedManager(models.Manager):
"""Custom manager to return only published posts."""
def get_queryset(self):
return super().get_queryset().filter(status='published')
def featured(self):
return self.get_queryset().filter(is_featured=True)
def by_author(self, author):
return self.get_queryset().filter(author=author)
def recent(self, count=5):
return self.get_queryset().order_by('-published_at')[:count]
class Post(models.Model):
# ... fields ...
status = models.CharField(max_length=10, default='draft')
# Default manager
objects = models.Manager()
# Custom manager
published = PublishedManager()
# Usage:
Post.published.all() # All published posts
Post.published.featured() # Featured published posts
Post.published.by_author(user) # Published posts by user
Post.published.recent(10) # Latest 10 published posts
Model Signals
python example
from django.db.models.signals import post_save, pre_save, post_delete
from django.dispatch import receiver
from django.contrib.auth.models import User
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
"""Create a profile whenever a new User is created."""
if created:
UserProfile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
"""Save user profile whenever user is saved."""
instance.profile.save()
@receiver(pre_save, sender=Post)
def set_published_date(sender, instance, **kwargs):
"""Automatically set published_at when status changes to published."""
from django.utils import timezone
if instance.status == 'published' and not instance.published_at:
instance.published_at = timezone.now()Summary
In this lesson, you learned:
- ✅ Defining Django models with various field types
- ✅ Configuring relationships (ForeignKey, ManyToMany, OneToOne)
- ✅ Creating and applying migrations
- ✅ Querying the database with the ORM (filter, get, exclude)
- ✅ Complex queries with Q objects
- ✅ Aggregation and annotation
- ✅ Optimizing queries (select_related, prefetch_related)
- ✅ Creating, updating, and deleting records
- ✅ Custom model managers
- ✅ Model signals for automation
*Next Lesson: Django Views →*
Continue the lesson path
Study next in this module
01Web DevelopmentIntroduction to DjangoLearn Django, Python02Web DevelopmentDjango REST API with DRFBuild professional REST APIs with Django REST Framework (DRF). Learn serializers, ViewSets, routers, authentication, permissions, filtering, pagination, and testing REST APIs in Django.03Web DevelopmentDjango ViewsMaster Django views — function-based views (FBVs), class-based views (CBVs), generic views, mixins, authentication, form handling, and REST-style view patterns with full practical examples.04Web DevelopmentIntroduction to FlaskLearn Flask, the lightweight Python web framework. Build your first web application, understand Flask