Django:具有不同字段的模型(实体属性值模型)

Django: Model with varying fields (Entity-Attribute-Value model)

我有以下 Django 模型来将稀疏产品数据存储在关系数据库中。对于下面代码中的任何错误关系,我深表歉意(ForeignKey and/or ManyToMany 可能放置错误,我现在只是在玩 Django)。

class ProdCategory(models.Model):
    category = models.CharField(max_length=32, primary_key=True)

class ProdFields(models.Model):
    categoryid = models.ForeignKey(ProdCategory)
    field = models.CharField(max_length=32)

class Product(models.Model):
    name = models.CharField(max_length=20)
    stock = models.IntegerField()
    price = models.FloatField()

class ProdData(models.Model):
    prodid = models.ManyToManyField(Product)
    fieldid = models.ManyToManyField(ProdFields)
    value = models.CharField(max_length=128)

想法是将每个产品的名称库存价格存储在一个 table 和另一个 table.[= 格式的 (id, value) 格式的每个产品的信息12=]

我确实知道每个产品类别应该具有的字段。例如,类型为 Desktop 的产品应具有 内存大小存储大小 作为字段,而类别 Monitor 的另一个产品应具有 resolutionscreen size 作为字段。

我的问题是:在 Django 中,我如何保证每个产品只包含其类别的字段?更准确地说,当指定类别 Monitor 的产品时,如何确保只有 resolutionscreen size是 ProdData 中的字段 table?

我发现了一个类似的问题Django: Advice on designing a model with varying fields,但没有关于如何确保上述内容的答案。

提前致谢。

Django 是一个优秀的框架,但它仍然只是对关系数据库的抽象。

你问的问题在关系数据库中是不可能有效的,所以在 Django 中很难做到。主要是因为在某些时候您的代码需要转换为 tables.

基本上有两种方法可以做到这一点:

  1. A product class 与属性 table:

    具有 ManyToMany 关系
    class Product(models.Model):
        name = models.CharField(max_length=20)
        stock = models.IntegerField()
        price = models.FloatField()
        product_type = models.CharField(max_length=20)  eg. Monitor, desktop, etc...
        attributes = models.ManyToManyField(ProductAttribute)
    class ProductAttribute(models.Model):
        property = models.CharField(max_length=20) # eg. "resolution"
        value = models.CharField(max_length=20) # eg. "1080p"
    

    但是,您围绕具有某些属性的某些 classes 对象的逻辑将会丢失。

  2. 使用继承。 Django 只是 Python,当然可以继承 - in fact its encouraged:

    class Product(models.Model):
        name = models.CharField(max_length=20)
        stock = models.IntegerField()
        price = models.FloatField()
    
    class Desktop(Product):
        memory_size = models.CharField(max_length=20)
        storage_size = models.CharField(max_length=20)
    class Monitor(Product):
        resolution = models.CharField(max_length=20)
        screen_size = models.CharField(max_length=20)
    

    然后您可以查询所有产品 - Products.objects.all() - 或仅查询监视器 - Monitor.objects.all()` - 等等。这在代码中对可能的产品进行硬编码,因此新产品类型需要数据库迁移,但它也使您能够将业务逻辑嵌入模型本身。

您需要权衡这两种方法,因此选择取决于您。