OneToOneField vs ForeignKey in django

The basic difference between a OneToOneField and a ForeignKey in django lies in the fact that one creates a one to one relationship between two entities and the other, a many-to-one relationship.

A one to one relationship between object A and B states that one member of A can only be associated with one member of B, and vice-versa. Mathematically, it represents a bijective function. An example is the relation between a User and a Profile on a blogging website. A user has a profile and each profile belongs to a particular User. So, we use a OneToOneField for creating this association.

On the other hand, a many to one relationship between object A and B states that, a member of object A is related to only one member of B, a member of object B can have many associations with member of object A. An example is the relation between a blog and a user. A blog is associated with only one user, whereas a user can be related to (i.e, author) multiple blogs at once. So, we create a foreignkey for creating this association.

In our models.py file:


from django.db import models

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

    def __str__(self):
        return self.name

class Profile(models.Model):
    author = models.OneToOneField(Author, on_delete=models.CASCADE)
    bio = models.CharField(max_length=300)

    def __str__(self):
        return self.author.name

class Blog(models.Model):
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    content = models.TextField()

    def __str__(self):
        return "%s written by %s" % (self.title, self.author)

Let us test the usage of these models in our django shell. After importing these models, let us first save a few Authors.

>>> a1 = Author(name='Rohan')
>>> a1.save()
>>> a2 = Author(name='Neha')
>>> a2.save()

Let us create a profile for a1:

>>> p1 = Profile(author=a1, bio='Life’s good')
>>> p1.save()

Since, it is a two way relationship, a profile can access an author, and an author can access a profile(if available).

>>>a1.profile
>>>p1.author

Both return valid objects.

Coming to the Blog, adding a blog associated with author a1.

>>>blog1=a1.blog_set.create(title=’Blog Title!’, content=’First blog content!’)

Notice that we don’t need to explicitly mention the author for this blog, this method, by default creates the blog with author set as a1.

Django has a lot of functionality when it comes to these relationships, more can be found out about them at docs for one to one relationship and docs for many to one relationship