Django,把OneToOne相关的字段当作我自己的字段



我本质上是在尝试制定自己的继承方案,因为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")  

我想列出不同种类的产品(数据)

  1. 我需要将它们一起列出,所以抽象的Base继承是不可用的

  2. 从列表中,我想将每个模型视为多态模型,当在ProductBase.objects.all()上迭代时,product.get_price()将使用适当的classe方法。(如果不必加入,则无需加入)

  3. 当并且只有当我想要的时候,我才会检索附加表数据(通过类似.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

从一个实际上是FooProductProductBase对象中,您可以使用获得自定义字段

product.foo.fooextra

从一个实际上是BarProductProductBase对象中,您可以使用获得自定义字段

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()将为您提供FooProductBarProduct对象,而不是ProductBase对象。

相关内容

最新更新