【问题标题】:Django: Model with varying fields (Entity-Attribute-Value model)Django:具有不同字段的模型(实体-属性-值模型)
【发布时间】:2015-11-11 22:19:27
【问题描述】:

我有以下 Django 模型将稀疏的产品数据存储在关系数据库中。对于以下代码中的任何错误关系,我深表歉意(ForeignKey 和/或 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)

这个想法是将每个产品的 namestockprice 存储在一个表中,并将每个产品的信息存储在 ( id, value) 格式在另一个表中。

我事先知道每个产品类别应具有的字段。例如,一个 Desktop 类型的产品应该有 memory sizestorage size 作为字段,而另一个 类别的产品>Monitor 应该有 resolutionscreen size 作为字段。

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

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

提前谢谢你。

【问题讨论】:

    标签: python django entity-attribute-value


    【解决方案1】:

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

    您所问的问题在关系数据库中无法有效实现,因此在 Django 中很难做到。主要是因为在某些时候您的代码需要转换为表格。

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

    1. 与属性表有ManyToMany 关系的product 类:

      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"
      

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

    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()` - 等等。这会将可能的产品硬编码在代码中,因此新产品类型需要数据库迁移,但它也使您能够将业务逻辑嵌入模型本身。

    这两种方法都需要权衡取舍,您需要自行决定。

    【讨论】:

    • 谢谢。我会在我的建模中考虑到这一点。您提出的方法在性能方面是否存在缺陷?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 2016-01-27
    • 1970-01-01
    • 2015-08-22
    • 1970-01-01
    • 2011-12-09
    相关资源
    最近更新 更多