Django 中产品目录的最佳实践

Joh*_*eer 5 python django database-design

我正在开发一个目录应用程序,用于在 Django 中存储产品信息。

这里的挑战是目录中有很多产品,每种产品都有自己的属性。由于这是应用程序的关键部分,并且将围绕它构建很多内容,因此我希望将其设计得尽可能好。

我知道 Django 中有多种处理此问题的选项,但我想知道其他人对这几种选项的体验。

第一种选择:单一抽象类

我可以创建一个包含所有基本属性的抽象类,并让其他类从该类派生。

class Product(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(max_length=1000)
    price = models.DecimalField()

    class Meta:
        abstract = True

class Phone(Product):
    series = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)

这将是最简单的选择,但这将包括 Django 表单和视图中的大量工作。
这还将为每个 Product 子类创建一个表,因此当 Product 类更改时,所有其他表也必须更改。

第二个选项:产品基类

这里的 Product 类不是抽象的,这意味着也可以使用该类。

class Product(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(max_length=1000)
    price = models.DecimalField()

class Phone(Product):
    series = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)

这也非常简单,但这仍然意味着表单和视图中的大量工作。
这将首先为 Product 类创建一个表,然后为每个 Product 子类创建一个表。

前两个选项也将打破 DRY 原则,因为必须将属性添加到每个 Product 子类中,这些子类可能对某些类(但不是所有类)通用。

第三个选项:包含所有可能属性的产品类。

class Product(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(max_length=1000)
    price = models.DecimalField()

    # attributes for phones, tv's, etc...
    series = models.CharField(max_length=100)


class PhoneForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'description', 'price', 'series']
Run Code Online (Sandbox Code Playgroud)

必须为每个产品子类创建一个新表单。这看起来确实很简单,但产品模型会变得非常臃肿。

在这种情况下,我还可以使用代理模型。

第四个选项:创建抽象类并使用类 Mixins

class ProductBase(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(max_length=1000)
    price = models.DecimalField()

    class Meta:
        abstract = True

class ElectronicsProduct(models.Model):
    series = models.CharField(max_length=100)

    class Meta:
        abstract = True

class Phone(ProductBase, ElectronicsProduct):
    pass
Run Code Online (Sandbox Code Playgroud)

这种方法可以解决我遇到的 DRY 问题和上面的问题,但仍然不是最佳的。

第五种选择:具有单独属性模型的一个产品模型

无论如何,这是我想使用的方法,但更多的是能够向过于具体而无法放入产品或产品子类的产品添加“额外”功能。

class Product(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(max_length=1000)
    price = models.DecimalField()

class Attribute(models.Model):
    name = models.CharField(max_length=100)

class ProductAttribute(models.Model):
    product = models.ForeignKey(Product)
    attribute = models.ForeignKey(Attribute)
    value = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)

这里的问题是这个方法是否应该用于所有产品属性,因为我认为这会增加数据库的大量开销。

这里的另一个挑战是值类型。在这种情况下,我只能使用字符值,那么当我想使用 Decimal 值或 File 时会发生什么?

第六个选项:其他

可能有一些方法我目前还没有想到。所以,如果你知道一些我不知道的事情,请与我分享。

我在这里不是寻求任何意见,而是寻求一些解决方案。因此,如果您对这个问题有答案,请告诉我们您为什么要使用您建议的方法。