Relationships

Link models with ForeignKey, ManyToManyField and OneToOneField.

Syntaxmodels.ForeignKey(Other, on_delete=models.CASCADE)

Real data is connected. Django models three kinds of relationships:

  • ForeignKey — many-to-one (many posts belong to one author).
  • ManyToManyField — many-to-many (a post has many tags, a tag has many posts).
  • OneToOneField — one-to-one (a user has one profile).

Django adds a reverse accessor automatically, so you can go both directions.

Example

Example · python
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

class Tag(models.Model):
    name = models.CharField(max_length=50)

class Post(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="posts")
    tags = models.ManyToManyField(Tag, related_name="posts")

# Usage:
# post.author.name       -> forward
# author.posts.all()     -> reverse (related_name)

When to use it

  • A developer adds a ForeignKey from Comment to Post so each comment belongs to exactly one post.
  • A blog uses ManyToManyField for tags so one post can have many tags and each tag can apply to many posts.
  • A developer uses OneToOneField to extend the built-in User model with a UserProfile containing extra fields.

More examples

ForeignKey (many-to-one)

Links Comment to Post with a ForeignKey; CASCADE deletes comments when the post is deleted.

Example · python
class Comment(models.Model):
    post = models.ForeignKey(
        "Post",
        on_delete=models.CASCADE,
        related_name="comments",
    )
    body = models.TextField()
    created = models.DateTimeField(auto_now_add=True)

ManyToManyField

Defines a many-to-many relationship between Post and Tag and shows how to add and query tags.

Example · python
class Tag(models.Model):
    name = models.CharField(max_length=50, unique=True)

class Post(models.Model):
    title = models.CharField(max_length=250)
    tags = models.ManyToManyField(Tag, blank=True, related_name="posts")

# Usage:
post.tags.add(tag_obj)
post.tags.all()

OneToOneField for profile extension

Uses OneToOneField to attach a UserProfile to the built-in User model without replacing it.

Example · python
from django.contrib.auth import get_user_model

User = get_user_model()

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/", null=True, blank=True)

Discussion

  • Be the first to comment on this lesson.