我目前正在 Django 中设计一个产品数据模型来管理工业机械的详细信息。挑战在于一些产品具有通用规格,而另一些产品则具有额外的独特规格。由于产品属性的可变性,修复单个模型中的所有字段是不可行的。
例如:
产品 A 和 产品 B 共享
weight
、power
和 dimensions
等属性。
产品C有
operating temperature
和safety standards
等独特规格,并不适用于所有产品。
在 Django 中设计灵活且可扩展的数据模型的最佳方法是什么:
将常见字段指定为产品上的字段,对于不常见字段使用 Entity-Attribute-Value (EAV) 模型 [wiki]。
因此,您可以构建一个
Attribute
模型,它本质上是一个名称(也许还有一些其他属性):
class Attribute(models.Model):
name = models.CharField(max_length=128, unique=True)
def __str__(self):
return self.name
以及包含每个产品价值的
AttributeValue
模型,例如:
class AttributeValue(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
value = models.FloatField()
def __str__(self):
return f'{self.product_id} {self.attribute_id}: {self.value}'
class Meta:
constraints = [
models.UniqueConstraint(
fields=('product', 'attribute'),
name='unique_attributes_per_product',
)
]
这会线性化每个产品的属性值,但优点是您仍然可以有效地过滤这些属性值。例如,我们可以使用以下方法检索
Product
小于 10(千克)的 weight
:
Product.objects.filter(
attributevalue__attribute__name='weight', attributevalue__value__lte=10
)
如果您有多种类型的值,我认为在这种情况下为每个type值附加一个 EAV 是有意义的(因此对于类似字符串的数据来说是一个单独的 EAV)。
JSONFIeld
model 字段[Django-doc] 将 JSON blob 添加到数据中。优点是它允许轻松地将各种数据转储到每个产品的 blob 中。缺点是,对 JSON blob 进行过滤通常效率不高,并且它不是从数据库存储和检索数据的最紧凑方式:每次获取 Product
时,也会检索所有属性,但是本身没有必要:
class Product(models.Model):
# …
extra_attributes = models.JSONField()