Home > OS >  Is it possible to have a OneToOneField in Django that's only null=True in one direction?
Is it possible to have a OneToOneField in Django that's only null=True in one direction?

Time:05-27

Is it possible to create a OneToOneField in Django that is only null=True in one direction?

Ex:

class Building(models.Model):
    ...

class Roof(models.Model):
    building = models.OneToOneField(...)
    ...

A building doesn't technically need to have a roof. Plenty of unfinished buildings don't have them. But you can't have a roof without a building.

Also, a building can only have one roof, and a roof can only be on one building, hence OneToOneField.

CodePudding user response:

Your models as setup already accomplishes that.

b1 = models.Building.objects.create()  # no error
b2 = models.Building.objects.create()  # no error
r1 = models.Roof.objects.create()      # violates null constraint

psycopg2.errors.NotNullViolation: null value in column "building_id" of 
relation "users_roof" violates not-null constraint

r2 = models.Roof.objects.create(building=b2) # no error

You're left with Building b1 with no Roof, and Building b2 with Roof r2.

Keep in mind that OneToOneField is not "symmetric", in the sense that it matters which of the two models you put the field in. With your models as defined, you will basically end up with an underlying Building database table with no mention of Roof, and a Roof table that contains a column with a foreign key (with a unique constraint) back to Building. That is why creating a Building does not require specifying a Roof, but creating a Roof requires specifying the associated Building.

  • Related