2

我开始在 Django 中创建一个网上商店。它将有不同种类的产品,如衬衫、海报、杯子、贴纸。每种类型的产品都有不同的字段。例如:衬衫有尺寸和颜色选项,贴纸有尺寸选项,海报和杯子没有选项。

做这个的最好方式是什么?遗产?关系?

我仍在学习 Django,并希望在深入研究此类项目之前从更有经验的人那里了解这一点。

谢谢

4

1 回答 1

3

这是一个有趣的问题。我相信首先您必须确定您的用户是否愿意自己添加项目类型,或者是否会有预定义数量的类型,并且只有开发人员可以在需要时添加新的类型。

静态项目类型

如果项目类型是静态的,您可以使用模型继承来创建您的模式。因此,在这种情况下,我建议为每个项目类型定义一个或多个抽象基础模型和具体模型。例如你会做这样的事情:

类项目(模型。模型):
  蛞蝓 = 模型.SlugField()
  价格 = 模型.DecimalField()
  剩余 = 模型.IntegerField()
  描述 = 模型.CharField()

  元类:
    抽象=真

类服装项目(项目):
  大小 = 模型.CharField()
  品牌 = 模型.CharField()

  元类:
    抽象=真

类夹克(服装项目):
  has_hood = models.BooleanField()

类帽子(服装项目):
  hat_type = models.CharField(choices=[])  

因此,上面实际上只会生成两个数据库表:Jacket 和 Hat,每一个都将包含它继承的模型中的所有字段。这是大多数人在 django 中使用的,因为它非常干净,使得添加表单和生成查询以获取项目非常容易。

您的其他选择是不使用抽象基类,因此您将获得一个名为的数据库表Item,该表将包含每个字段,另一个名为ClothingItem的表将包含一个 ForeignKeyItem和另一个命名Jacket的表将包含一个 ForeignKey ClothingItem。这将帮助您在Itemor上生成聚合ClothingItem,但是当您想要获取 Jacket 的属性时,django 将不得不查询三个表(带有连接)。我建议仅在您确定需要它时才使用它。

动态项目类型 在这种情况下,您必须使用不同的模式,因为项目的属性必须由应用程序的用户定义。你可以这样做:

类类别(模型。模型):
  名称 = 模型.CharField()

类属性(models.Model):
  类别=模型.ForeignKey(类别)
  名称 = 模型.CharField

类项目(模型。模型):
  蛞蝓 = 模型.SlugField()
  价格 = 模型.DecimalField()
  剩余 = 模型.IntegerField()
  类别=模型.ForeignKey(类别)
  描述 = 模型.CharField()
  属性 = models.ManyToManyField(属性,通过='ItemAttribute')

类 ItemAttribute(models.Model):
  item=models.ForeignKey(Item)
  属性 = 模型.ForeignKey(属性)
  值 = 模型.CharField()

这种设计稍微复杂一些。我们这里有一个类别模型,它将定义您的项目类型(帽子、夹克、杯子、衬衫、海报等)——您还可以定义类别的层次结构,我将把它留给您作为练习。属性模型定义了属性的名称——每个属性都有一个名称和它所属的类别。因此,对于夹克类别,您将拥有一个 has_hood 属性,对于帽子类别,您将拥有一个 hat_type 属性等。

现在,一个 Item 模型也属于一个 Category 并且通过 ItemAttribute 模型与 Attribute 模型具有多对多的关系。最后一个意味着您将在数据库中拥有一个 ItemAttribute 表,其中包含以下字段:

项目 - 属性 - 值

因此夹克 312 将具有值为 true 的属性 2(has_hood),而夹克 313 将具有值为 false 等的属性 2。

上面的设计有个小问题,就是属性中没有“类型”。您应该通过将 _type 属性添加到 Attribute 模型来进一步扩展它。另外,请检查这个问题的答案: Django 动态模型字段,它以更通用的方式定义动态模型字段。

通过这种设计,您的用户将能够创建新属性,将它们分配给类别,因此当他们添加新项目时,他们将能够根据他们的类别填充他们的属性。当然,为了让您的用户能够做到这一点,您还必须生成包含每个项目的动态属性的动态表单。如果你愿意,我也可以告诉你如何做到这一点——它并不像人们起初认为的那么难(提示:用于type生成动态 Form 类)。

于 2013-08-22T06:06:07.030 回答