Episode 27 of 32

Foreign Keys

Link articles to users with foreign keys — understand database relationships and how to automatically assign the logged-in user as the author.

Foreign Keys

A ForeignKey creates a relationship between two models. Each article belongs to one user (the author), and each user can have many articles. This is a one-to-many relationship.

The Foreign Key Field

# articles/models.py
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField()
    body = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    thumb = models.ImageField(default='default.png', blank=True)
    author = models.ForeignKey(
        'auth.User',
        on_delete=models.CASCADE,
        default=None
    )

on_delete Options

OptionBehavior
CASCADEDelete articles when user is deleted
PROTECTPrevent user deletion if they have articles
SET_NULLSet author to null (requires null=True)
SET_DEFAULTSet author to the default value

Setting the Author Automatically

# In the create view:
def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST, request.FILES)
        if form.is_valid():
            instance = form.save(commit=False)
            instance.author = request.user  # Set author to logged-in user
            instance.save()
            return redirect('articles:list')

Querying Related Objects

# Get all articles by a user
user_articles = Article.objects.filter(author=request.user)

# Access the author from an article
article = Article.objects.get(id=1)
print(article.author.username)

# Reverse lookup — get articles from the user object
articles = request.user.article_set.all()

Displaying the Author

<!-- In templates -->
<p>Written by {{ article.author.username }}</p>

Key Takeaways

  • ForeignKey creates a one-to-many relationship between models
  • on_delete=models.CASCADE deletes related objects when the parent is deleted
  • Set the author with commit=False + instance.author = request.user
  • Use article.author.username in templates to display the author name