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

时间:2015-11-11 22:19:28

标签: python django entity-attribute-value

我有以下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)

我们的想法是将每个产品的名称股票价格存储在一个表格中,并将每个产品的信息存储在(另一个表格中的 id )格式。

我事先知道每个产品类别应该具有的字段。例如,桌面类型的产品应该包含内存大小存储大小作为字段,而另一类产品监视器应将分辨率屏幕尺寸作为字段。

我的问题是:在Django中,我如何保证每个产品只包含其类别的字段?更准确地说,在指定类别监视器的产品时,如何确保只有分辨率屏幕尺寸是ProdData表中的字段?

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

提前谢谢。

1 个答案:

答案 0 :(得分:2)

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

在关系数据库中无法有效地提出要求,因此在Django中很难做到。首先,因为在某些时候您的代码需要转换为表格。

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

  1. 与属性表product关系的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"
    

    但是,你对某些具有某些属性的对象的逻辑将会丢失。

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

  3. 这两种方法需要权衡,你需要决定,所以选择取决于你。