我本质上是在尝试制定自己的继承方案,因为Django的继承不符合我的需求。
我希望父表(类)包含公共数据字段
子类在一个单独的表中有自己的附加数据。
class ProductBase(models.Model):
common = models.IntegerField()
def get_price(self):
return some_price
class FooProduct(ProductBase):
# no field because I'm proxy
class Meta:
proxy = True
def get_price(self):
return price_using_different_logic
class FooExtra(models.Model):
base = models.OneToOneField(ProductBase, primary_key=True)
phone = models.CharField(max_length=10)
我的问题是,它是否能够将Foo视为具有FooExtra
的字段?
我想做以下事情。。
foo = FooProduct.objects.create()
foo.phone = "3333" # as django does with its multiple inheritance
foo.save()
FooProduct.objects.filter(phone="3333")
我想列出不同种类的产品(数据)
我需要将它们一起列出,所以抽象的Base继承是不可用的
从列表中,我想将每个模型视为多态模型,当在ProductBase.objects.all()上迭代时,product.get_price()将使用适当的classe方法。(如果不必加入,则无需加入)
当并且只有当我想要的时候,我才会检索附加表数据(通过类似
.select_related('fooextra')
的方式
Django多态性接近我想要的,但它的作用相当模糊,所以我害怕使用它,我认为它失败了#3。
如果我理解得很好,您希望继承,并且希望子类特定的字段在一个单独的表上。据我所知,您不需要代理类来实现这一点,只需按照手册中的说明实现多表继承即可https://docs.djangoproject.com/en/1.9/topics/db/models/#multi-表继承,例如:
class Base(models.Model):
common = models.IntegerField()
class Foo(Base):
phone = models.CharField(max_length=10)
如上链接所述,这将自动创建一对一的关系。当然,您可以像上面的例子一样执行foo.phone = "3333"
(其中foo
属于Foo
类型)。巧妙的是,你也可以访问foo.common
,而在你的例子中,它应该是foo.base.common
。
您似乎不希望与Django的标准继承有任何不同。
class ProductBase(models.Model):
common1 = models.IntegerField()
common2 = models.IntegerField()
class FooProduct(ProductBase):
fooextra = models.IntegerField()
class BarProduct(ProductBase):
barextra = models.IntegerField()
如果您创建每个实例:
foo1 = FooProduct(common1=1, common2=1, fooextra=1)
foo2 = FooProduct(common1=1, common2=1, fooextra=2)
bar1 = BarProduct(common1=1, common2=1, barextra=1)
bar2 = BarProduct(common1=1, common2=1, barextra=2)
您可以循环浏览所有产品:
for product in ProductBase.objects.all():
print product.common1, product.common2
从一个实际上是FooProduct
的ProductBase
对象中,您可以使用获得自定义字段
product.foo.fooextra
从一个实际上是BarProduct
的ProductBase
对象中,您可以使用获得自定义字段
product.bar.barextra
您仍然可以进行查询:
foo = FooProduct.objects.get(fooextra=1)
bar = BarProduct.objects.get(barextra=2)
您可以直接访问这些对象上的公共字段:
foo.common1
bar.common2
如果您需要对查询等进行更多控制,则可以使用django模型utils中的InheritanceManager
,这也应该解决第3点:ProductBase.objects.filter(...).select_subclasses()
将为您提供FooProduct
和BarProduct
对象,而不是ProductBase
对象。