A Complete Guide to One‑to‑One Relationships in Django Using OneToOneField

This article explains how to define and work with one‑to‑one relationships in Django using OneToOneField. It covers creating related objects, accessing relationships from both sides, reassigning one‑to‑one links, querying across relationships, deletion behavior with CASCADE, and working with related models such as Waiter. All concepts are demonstrated with practical Python API examples.

OneToOneField, one-to-one relationshipDjango ORM, CASCADEreverse relation, waiter_set

~2 min read • Updated Mar 10, 2026

1. Defining a One‑to‑One Relationship

A one‑to‑one relationship is defined using OneToOneField. In the example below, each Place may optionally have one Restaurant, and each Restaurant corresponds to exactly one Place.


class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(models.Model):
    place = models.OneToOneField(
        Place,
        on_delete=models.CASCADE,
        primary_key=True,
    )
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

2. Creating Data

Creating Place instances:


p1 = Place(name="Demon Dogs", address="944 W. Fullerton"); p1.save()
p2 = Place(name="Ace Hardware", address="1013 N. Ashland"); p2.save()

Creating a Restaurant:

The Restaurant uses the Place as its primary key:


r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)
r.save()

3. Accessing the Relationship

Restaurant → Place:


r.place

Place → Restaurant:


p1.restaurant

If a Place has no Restaurant:


hasattr(p2, "restaurant")  # False

4. Reassigning a One‑to‑One Relationship

You can assign a Restaurant to a different Place:


r.place = p2
r.save()
p2.restaurant  # Now belongs to p2

And assign it back from the reverse side:


p1.restaurant = r
p1.restaurant

Important: The related object must be saved first


p3 = Place(name="Demon Dogs", address="944 W. Fullerton")
Restaurant.objects.create(place=p3, ...)  # ValueError

5. Querying Across One‑to‑One Relationships

Restaurant → Place:


Restaurant.objects.get(place=p1)
Restaurant.objects.filter(place__name__startswith="Demon")
Restaurant.objects.exclude(place__address__contains="Ashland")

Place → Restaurant:


Place.objects.get(restaurant=r)
Place.objects.get(restaurant__place__name__startswith="Demon")

6. Deletion Behavior (CASCADE)

Deleting a Place deletes its Restaurant automatically:


p2.delete()
Restaurant.objects.all()  # Only the restaurant for p1 remains

7. Related Models: Waiter

In the example, Waiter has a ForeignKey to Restaurant:


w = r.waiter_set.create(name="Joe")

Querying Waiters:


Waiter.objects.filter(restaurant__place=p1)
Waiter.objects.filter(restaurant__place__name__startswith="Demon")

Conclusion

One‑to‑one relationships in Django are ideal when two models should form a strict pair. Using OneToOneField, you can easily define the relationship, navigate it from both sides, reassign linked objects, and perform expressive queries. Django’s reverse managers and lookup chaining make working with one‑to‑one relationships intuitive and powerful.

Written & researched by Dr. Shahin Siami