如何在Django中访问“子模型”的方法?

时间:2012-08-10 00:05:41

标签: python django django-models

在Django中,我有以下models.py

class Product(RandomPrimaryIdModel):
  feature1 = models.CharField(max_length=20, blank=True, null=True)
  feature2 = models.CharField(max_length=20, blank=True, null=True)
  feature3 = models.CharField(max_length=20, blank=True, null=True)

class Mattress(Product):
  category_type = models.CharField(max_length=50)
  size = models.CharField(max_length=5)

  def category(self):
    return "bedding"
  category = property(category)

我有以下views.py文件

def update(request, id):
  product = Product.objects.get(id=id)
  ...

在此方法中,我可以从Product模型中调用“Mattress”模型中定义的方法。例如,我想写:if product.type ==“mattress”,其中类型已在Mattress模型中定义,而Mattress是Product的子模型。

2 个答案:

答案 0 :(得分:3)

您的示例似乎介于两种不同的方式之间,但目前不正确。发生的事情是你创建了两个表:Product和Mattress,它们完全不相关。无论Mattress是Product的子类,它只是继承了它的结构。您无法在产品表中查询有关床垫的任何信息,因为床垫位于床垫表中。

一种方法是将产品视为抽象的,由实际产品进行子类化:

class Product(RandomPrimaryIdModel):
    class Meta:
        abstract=True

这将阻止创建Product表。然后您可以通过以下方式直接查询床垫:Mattress.objects.filter()

但这在引入多种类型的产品方面似乎有点限制,并且必须为它们管理不同的表。另一种方法是使用Product表,但使用泛型关系来支持将任何类型的其他表作为内容对象附加:

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Product(RandomPrimaryIdModel):

    feature1 = models.CharField(max_length=20, blank=True, null=True)
    feature2 = models.CharField(max_length=20, blank=True, null=True)
    feature3 = models.CharField(max_length=20, blank=True, null=True)

    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

有了这个,您就可以将content_object设置为Mattress实例。然后,您可以使用ContentType进行查询:

p_type = ContentType.objects.get(name="mattress")
Product.objects.filter(content_type=p_type)

答案 1 :(得分:0)

这看起来像是自动向下投射的情况。对于拥有通用“ProductBase”实例的购物车,我需要类似的方法,但我需要访问子项的特定功能,这些功能是ProductDownloadable,ProductShipped等类型的实际产品。

Django本身并不支持这个,但可以通过内省或使用django-model-utils对其进行编码,一旦安装完就可以:

# return a list 'child' classes of Product - in your case Mattresses
mattress_list = Product.objects.all().select_subclasses() 

# return the direct 'child' class of Product - in your case Mattress class
mattress = Product.get_subclass(id=some_id) # returns the 'child' subclass
mattress.foo() # executes method on foo on Mattress class (not on Product class)