Model Relationships — ForeignKey
ForeignKey creates a many-to-one relationship — many posts belong to one author, many comments belong to one post. It's the most common relationship type in Django. ForeignKey adds a column in the database table that references another table's primary key.
20 min•By Priygop Team•Updated 2026
ForeignKey Basics
- ForeignKey(Model, on_delete=...) — Many-to-one relationship
- on_delete=CASCADE — Delete related objects when parent is deleted
- on_delete=PROTECT — Prevent deletion if related objects exist
- on_delete=SET_NULL — Set to NULL (requires null=True)
- on_delete=SET_DEFAULT — Set to default value
- related_name — Name for the reverse relation
- Access forward: post.author (returns User object)
- Access reverse: user.posts.all() (returns QuerySet)
ForeignKey Example
ForeignKey Example
# blog/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)
#
# def __str__(self):
# return self.name
# class Post(models.Model):
# title = models.CharField(max_length=200)
# content = models.TextField()
# # ForeignKey — Many posts -> One author
# author = models.ForeignKey(
# User,
# on_delete=models.CASCADE,
# related_name='posts'
# )
# # ForeignKey — Many posts -> One category
# category = models.ForeignKey(
# Category,
# on_delete=models.SET_NULL,
# null=True, blank=True,
# related_name='posts'
# )
# created_at = models.DateTimeField(auto_now_add=True)
# Usage:
# post = Post.objects.get(pk=1)
# post.author # User object
# post.author.username # 'alice'
# post.category # Category object
#
# # Reverse relation
# user = User.objects.get(username='alice')
# user.posts.all() # All posts by alice
# user.posts.count() # Number of postsTip
Tip
QuerySets are lazy — they don't hit the database until evaluated. Chain filters freely without performance cost.
Diagram
Loading diagram…
QuerySets are LAZY — no DB hit until evaluated.
Common Mistake
Warning
Using .get() without try/except. It raises DoesNotExist if not found. Use .filter().first() for safe access.
Practice Task
Note
(1) Use filter(), exclude(), order_by() in shell. (2) Chain multiple filters. (3) Try .get() with a non-existent pk.
Quick Quiz
Key Takeaways
- ForeignKey creates a many-to-one relationship — many posts belong to one author, many comments belong to one post.
- ForeignKey(Model, on_delete=...) — Many-to-one relationship
- on_delete=CASCADE — Delete related objects when parent is deleted
- on_delete=PROTECT — Prevent deletion if related objects exist