Relationships
Link models with ForeignKey, ManyToManyField and OneToOneField.
Syntax
models.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
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.
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.
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.
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