我有一个 Django 应用程序,它有许多不同的模型,都有一堆公共数据。最终,我认为这个问题归结为继承和组合之间的决定。我目前的实现是这样的:
class Thing(models.Model):
foo = models.FooField()
bar = models.BarField()
type = models.CharField()
class A(CommonStuff):
aFoo = models.FooField()
class B(CommonStuff):
bFoo = models.FooField()
使用此模型,我可以Thing
使用 Thing 模型的管理器查询 a。使用 上的类型字段Thing
,我可以通过查看type
包含“a”或“b”的字段,然后询问 (ie)来获取子对象数据thing.a.aFoo
。这是我喜欢的一个功能,因为它是我的应用程序中一个相当常见的操作,用于获取所有Thing
对象的列表。
我在这里看到几个问题。首先,该type
字段似乎没有必要。有没有办法在不必先查找类型的情况下获取子数据?似乎我可以使用一个实例方法来解决这个问题,该方法在给定类型值的情况下返回正确的对象,或者如果我真的想摆脱类型字段,我可以遍历每个反向关系字段Thing
,寻找一个这不会引发DoesNotExist
异常。不过,这对我来说感觉很脆弱。如果我添加一个新的 'subthing' C
,我必须更新Thing
以查找新类型。我可以通过制作Thing
和抽象模型来解决这个问题。这样,A
获得B
所有领域,Thing
我就不必使用type
场地。但是,问题是我失去了对所有Thing
对象执行查询的能力。
我正在考虑的另一种模型通过将数据Thing
转换为 onA
和的字段来颠覆这个模型B
。
class Thing(models.Model):
foo = models.FooField()
bar = models.BarField()
class A(models.Model):
aFoo = models.FooField()
thing = models.OneToOneField(Thing)
class B(models.Model):
bFoo = models.FooField()
thing = models.OneToOneField(Thing)
这个版本有一些好处。它摆脱了type
,Thing
而且——至少对我来说——看起来和感觉更干净,更不脆弱。但是,这里的问题与Thing
第一个版本中抽象的问题相同。我失去了同时查询所有“子事物”的能力。我可以查询A
对象或查询B
对象,但不能同时查询。可以使用这个版本的模型而不必牺牲查询所有“子事物”的能力吗?一种可能性是编写一个查询两个模型并返回QuerySet
所有对象的管理器。那样有用吗?