Django object composition with OneToOneField
As noted in other questions, Django experts like Two Scoops recommend explicit OneToOneFields rather than multi-table inheritance to avoid performance penalties of implicit joins. I have tried to follow such an approach, and my design is actually object composition, but have a few questions. All three of these are concrete tables.
class Widget:
... many shared fields ...
class FunWidget:
parent = models.OneToOneField(Widget, related_name='child', primary_key=True)
... fun-specific fields ...
class WorkWidget:
parent = models.OneToOneField(Widget, related_name='child', primary_key=True)
... work-specific fields ...
My questions are:
Related name: Given a Widget
, it'd be nice to refer to its related subtype with the same name, eg, Widget.child
. However, I get a Reverse query name for ... clashes with reverse query name for ...
error. Therefore, it seems I must provide different related_name
s, so that a given Widget
would have either a .funwidget
or a .workwidget
. To generalize I could provide a method Widget.child()
which checks each of the possible related_name
s, but that won't help me in queries.
Filtering by Subtype: Given a QuerySet
of Widget
, I need to filter to all which are of a given "subtype". I realize you'd normally just query the child model, but this is for a custom query set for Widget
where I need to perform different filtering based on the type of "subclass". In other words, I want something like this Widget.objects.filter(isinstance(child, WorkWidget))
which I realize isn't possible. Currently I am "duck typing" by checking for some different property of Widget (my dilemma from question 1 provides such a feature). Cleaner would be to store an explicit .type
field, if I must.
I've failed to find a simple example with this kind of explicit one-to-one mapping.
Simply check for the existence of the given subtype:
Widget.objects.select_related('workwidget').filter(workwidget__isnull=False)
上一篇: Django ORM将孩子的数量分组