这是一个有趣的问题。我相信,首先您必须弄清楚您的用户是否愿意自己添加项目类型,或者是否有预定义的类型数量,并且只有开发人员可以在需要时添加新的类型。
静态项目类型
如果项目类型是静态的,您可以使用模型继承来创建架构。因此,在这种情况下,我建议为每种项目类型定义一个或多个抽象基本模型和具体模型。例如你会做这样的事情:
class Item(models.Model):
slug = models.SlugField()
price = models.DecimalField()
remaining = models.IntegerField()
description = models.CharField()
class Meta:
abstract=True
class ClothingItem(Item):
size = models.CharField()
brand = models.CharField()
class Meta:
abstract=True
class Jacket(ClothingItem):
has_hood = models.BooleanField()
class Hat(ClothingItem):
hat_type = models.CharField(choices=[])
因此,上面的代码实际上只会生成两个数据库表:Jacket 和 Hat,每个表都将包含其继承的模型的所有字段。这是大多数人在 django 中使用的,因为它非常干净,使得添加表单和生成查询来获取项目变得非常容易。
您的其他选择是不使用抽象基类,因此您将获得一个名为的数据库表Item
其中将包含每个字段,另一个名为ClothingItem
它将包含一个外键Item
和另一个名叫Jacket
它将包含一个外键ClothingItem
。这将帮助您生成聚合Item
or ClothingItem
,但是每当你想要获取 Jacket 的属性时,django 都必须查询三个表(带有连接)。我建议仅当您确定需要它时才使用它。
动态项目类型在这种情况下,您必须使用不同的架构,因为项目的属性必须由应用程序的用户定义。你可以这样做:
class Category(models.Model):
name = models.CharField()
class Attribute(models.Model):
category = models.ForeignKey(Category)
name = models.CharField
class Item(models.Model):
slug = models.SlugField()
price = models.DecimalField()
remaining = models.IntegerField()
category = models.ForeignKey(Category)
description = models.CharField()
attributes = models.ManyToManyField(Attribute, through='ItemAttribute')
class ItemAttribute(models.Model):
item= models.ForeignKey(Item)
attribute = models.ForeignKey(Attribute)
value = models.CharField()
这个设计有点复杂。我们这里有一个类别模型,它将定义您的项目类型(帽子、夹克、杯子、衬衫、海报等)——您还可以定义类别的层次结构,我将把它作为练习留给您。属性模型定义了属性的名称 - 每个属性都有一个名称和它所属的类别。因此,对于夹克类别,您将具有 has_hood 属性,对于帽子类别,您将具有 hat_type 属性等。
现在,项目模型也属于类别并且具有通过 ItemAttribute 模型与 Attribute 模型建立多对多关系。最后一项意味着您将拥有
数据库中的 ItemAttribute 表包含以下字段:
item - attribute - value
因此,夹克 312 的属性 2(has_hood) 的值为 true,而夹克 313 的属性 2 的值为 false,等等。
上面的设计有一个小问题,就是属性中没有“类型”。您应该通过向属性模型添加 _type 属性来进一步扩展它。另外,请检查这个问题的答案:Django 动态模型字段 https://stackoverflow.com/questions/7933596/django-dynamic-model-fields/它以更通用的方式定义动态模型字段。
通过这种设计,您的用户将能够创建新属性,将它们分配给类别,因此当他们添加新项目时,他们将能够根据其类别填充其属性。当然,为了使您的用户能够执行此操作,您还必须生成动态表单,其中包含每个项目的动态属性。如果你愿意,我也可以告诉你如何做到这一点 - 这并不像有人一开始认为的那么困难(提示:使用type
生成动态表单类)。