2015-11-11 80 views
0

我有以下Django模型來在關係數據庫中存儲稀疏產品數據。我爲自己在下面的代碼中的任何錯誤關係表示歉意(ForeignKey和/或ManyToMany可能被錯誤地放置,我現在只是在玩Django)。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

Django是一個優秀的框架,但它仍然只是一個關係數據庫的抽象。

你所要求的在關係型數據庫中是不可能有效的,所以在Django中很難做到。主要是因爲在某些時候你的代碼需要轉換成表格。

基本上有2種方式,你可以這樣做:

  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()` - 等。這會在代碼中硬編碼可能的產品,因此新產品類型需要數據庫遷移,但它也使您能夠將業務邏輯嵌入到模型本身中。

這些方法都需要權衡,您需要決定哪些方法,因此挑選取決於您。

+0

謝謝。我將在我的建模中考慮到這一點。您提出的方法在性能方面是否存在任何缺陷? – b3rtz