Skip to main content

OneToOne

A OneToOne field is a ForeignKey with a UNIQUE constraint โ€” each row on one side relates to exactly one row on the other.

Defining a OneToOneโ€‹

class User(Model):
username = CharField(max_length=100, unique=True)
email = CharField(max_length=254, unique=True)

class Profile(Model):
user = OneToOneField(User, on_delete="CASCADE")
bio = CharField(max_length=500, null=True, blank=True)
avatar = CharField(max_length=500, null=True, blank=True)

This creates a user_id column with both a foreign key and a unique constraint.

When to Use OneToOneโ€‹

  • Extending a built-in model โ€” Add fields to a model you can't modify
  • Splitting large tables โ€” Keep frequently-accessed fields separate from rarely-used ones
  • Inheritance-like patterns โ€” Model subtypes without actual inheritance
# Base user data (frequently queried)
class User(Model):
username = CharField(max_length=100)
password = CharField(max_length=255)

# Extended profile (rarely queried)
class Profile(Model):
user = OneToOneField(User, on_delete="CASCADE")
bio = CharField(max_length=500, null=True)
website = CharField(max_length=200, null=True)
location = CharField(max_length=100, null=True)
# User โ†’ Profile
user = await User.objects.get(pk=1)
profile = await Profile.objects.get(user_id=user.pk)

# Profile โ†’ User
profile = await Profile.objects.get(pk=1)
print(profile.user.username) # Forward descriptor (lazy-loaded)

Next Stepsโ€‹

โ†’ ManyToMany โ€” Many-to-many relationships