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

时间:2021-06-05 12:58:50

I have the following Django model to store sparse product data in a relational database. I apologize myself for any wrong relationship in the code below (ForeignKey and/or ManyToMany might be wrongly placed, I am just playing around with Django for now).

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

The idea is to store the name, stock and price for each product in one table and the information for each product in the (id, value) format in another table.

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

I do know, a priori, the fields that each product category should have. For instance, a product of type Desktop should have, among others, memory size and storage size as fields, whereas another product of category Monitor should have resolution and screen size as fields.

我事先知道每个产品类别应该具有的字段。例如,Desktop类型的产品应具有内存大小和存储大小等字段,而Monitor类别的另一产品应具有分辨率和屏幕大小作为字段。

My question is: How do I guarantee, in Django, that each product contains only the fields for its category? More precisely, when specifying a product of category Monitor, how to assure that only resolution and screen size are fields in the ProdData table?

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

I found a similar question Django: Advice on designing a model with varying fields, but there was no answer on how to assure the above.

我发现了类似的问题Django:关于设计具有不同字段的模型的建议,但是没有关于如何确保上述问题的答案。

Thank you in advance.

先谢谢你。

1 个解决方案

#1


1  

Django is an excellent framework, but it is still just an abstraction over a relation database.

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

What you are asking isn't efficiently possible in a relational database, so it will be tough to do in Django. Primarily, because at some point your code will need to be converted to tables.

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

There are basically 2 ways you can do this:

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

  1. A product class with a ManyToMany relation to an attribute 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"
    

    But, your logic around certain classes of objects having certain properties will be lost.

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

  2. Use inheritance. Django is just Python, and inheritance is certainly possible - in fact its encouraged:

    使用继承。 Django只是Python,继承当然是可能的 - 事实上它鼓励:

    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)
    

    Then you can do queries on all products - Products.objects.all() - or just Monitors - Monitor.objects.all()` - and so on. This hard codes the possible products in code, so a new product type requires a database migration, but it also gives you the ability to embed your business logic in the models themselves.

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

There are trade-offs to both these approaches which you need to decide, so picking is up to you.

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

#1


1  

Django is an excellent framework, but it is still just an abstraction over a relation database.

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

What you are asking isn't efficiently possible in a relational database, so it will be tough to do in Django. Primarily, because at some point your code will need to be converted to tables.

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

There are basically 2 ways you can do this:

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

  1. A product class with a ManyToMany relation to an attribute 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"
    

    But, your logic around certain classes of objects having certain properties will be lost.

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

  2. Use inheritance. Django is just Python, and inheritance is certainly possible - in fact its encouraged:

    使用继承。 Django只是Python,继承当然是可能的 - 事实上它鼓励:

    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)
    

    Then you can do queries on all products - Products.objects.all() - or just Monitors - Monitor.objects.all()` - and so on. This hard codes the possible products in code, so a new product type requires a database migration, but it also gives you the ability to embed your business logic in the models themselves.

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

There are trade-offs to both these approaches which you need to decide, so picking is up to you.

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