在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.type == "床垫",其中类型已在床垫模型中定义,并且床垫是产品的子模型。
您的示例似乎介于两种不同的方式之间,但目前不正确。正在发生的事情是,您正在创建两个表:产品和床垫,它们完全不相关。不管床垫子类产品,它只是继承了它的结构。您无法查询产品表中有关床垫的任何内容,因为床垫位于床垫表中。
一种方法是将产品视为抽象的,由实际产品进行子类化:
class Product(RandomPrimaryIdModel):
class Meta:
abstract=True
这将阻止创建产品表。然后,您将通过以下方式直接查询床垫: 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
设置为床垫实例。然后,您可以使用内容类型进行查询:
p_type = ContentType.objects.get(name="mattress")
Product.objects.filter(content_type=p_type)
这看起来像是自动向下铸造的情况。对于包含通用"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)