Django OneToOneField - in which model should I put it?

自闭症网瘾萝莉.ら 提交于 2019-12-04 08:29:51

问题


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.


回答1:


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).




回答2:


OneToOneFields are really only for two purposes: 1) inheritance (Django uses these for its implementation of MTI) or 2) extension of a uneditable model (like creating a UserProfile for User).

In those two scenarios, it's obvious which model the OneToOneField goes on. In the case of inheritance, it goes on the child. In the case of extension it goes on the only model you have access to.

With very few exceptions, any other use of a one-to-one should really just be merged into one single model.




回答3:


I think the case of a OneToOne field, the correct answer is that it doesn't matter, it just depends on which model it makes more sense to relate to the other.




回答4:


By the way, I needed OneToOneField to prevent circular dependency (inheritance use):

Model A:
  ...
  current_choice = models.ForeignKey(B)

Model B:
  ...
  parent = models.ForeignKey(A)

That means, A needs B to be defined. Not a good database convention for bootstrapping. Instead I did:

Model A:
  ...

Model B:
  ...
  parent = models.ForeignKey(A)

Model C:
  parent = models.OneToOneField(A)
  current_choice = models.ForeignKey(B)

With respect to example from documentation, you can also have clean queries like: p1.restaurant.place.restaurant.place... This is madness.



来源:https://stackoverflow.com/questions/9800490/django-onetoonefield-in-which-model-should-i-put-it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!