简体   繁体   中英

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

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).

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.

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.

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?

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.

Thank you in advance.

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

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.

There are basically 2 ways you can do this:

  1. A product class with a ManyToMany relation to an attribute table:

     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 :

     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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM