Django OneToOneField - in which model should I put it?

aemdy picture aemdy · Mar 21, 2012 · Viewed 7.3k times · Source

Let's assume that we have the following models.

class A(Model): pass
class B(Model): pass

Then there is no difference between:

In model A: b = OneToOneField(B, related_name=A.__name__)

and

in model B: a = OneToOneField(A, related_name=B.__name__)

So what questions should I ask myself to decide whether to put OTO in one model or another. I mean like has-a, is-a and so on.

Answer

Erin Heyming picture Erin Heyming · May 23, 2012

There actually is a difference in where you put the one-to-one field, because deletion behaves differently. When you delete an object, any other objects that had one-to-one relationships referencing that object will be deleted. If instead you delete an object that contains a one-to-one field (i.e. it references other objects, but other objects are not referencing back to it), no other objects are deleted.

For example:

class A(models.Model):
    pass

class B(models.Model):
    a = models.OneToOneField(A)

If you delete A, by default B will be deleted as well (though you can override this by modifying the on_delete argument on the OneToOneField just like with ForeignKey). Deleting B will not delete A (though you can change this behavior by overriding the delete() method on B).

Getting back to your initial question of has-a vs. is-a, if A has a B, B should have the one-to-one field (B should only exist if A exists, but A can exist without B).