如何在Django模型中存储任意名称/值键对?

时间:2009-10-29 00:37:19

标签: django django-models

我有一个固定的数据模型,它有很多数据字段。

class Widget(Models.model):
    widget_owner = models.ForeignKey(auth.User)
    val1 = models.CharField()
    val2 = models.CharField()
    ...
    val568 = ...

我希望让我的用户指定自定义数据字段,将更多数据填充到此Widget中。什么是理智的方式来做到这一点?存储名称/值对,用户可以指定其他“窗口小部件字段”是个好主意吗?我的伪想法如下:

data_types = ('free_text', 'date', 'integer', 'price')
class CustomWidgetField(models.Model)
  owner = ForeignKey(auth.User)
  field_title = models.CharField(auth.User)
  field_value_type = models.CharField(choices = data_types)

class CustomWidgetValue(models.Model)
  field_type = ForeignKey(CustomWidgetField)
  widget = ForeignKey(Widget)
  value = models.TextField()

所以我想让每个用户构建一个新类型的数据字段,它将应用于所有小部件,然后为每个小部件中的每个自定义字段指定值。我可能不得不像在原生字段上那样对这些自定义字段进行过滤/搜索(我假设它比在本地字段上操作慢得多。)但是规模是每个Widget有几十个自定义字段和每个用户的库存中只有几千个小部件。我也可以将自定义字段的大部分搜索/过滤批量转换为后端脚本(可能。)

5 个答案:

答案 0 :(得分:21)

考虑用序列化的dict表示所有自定义属性。我在最近的一个项目中使用了它,它运行得非常好。

 class Widget(models.Model):
      owner = models.ForeignKey(auth.User)
      props = models.TextField(blank=True) # serialized custom data

      @property
      def props_dict(self):
          return simplejson.loads(self.props)

 class UserProfile(models.Model)
      user = models.ForeignKey(auth.User)
      widget_fields = models.TextField(blank=True) # serialized schema declaration

答案 1 :(得分:8)

看起来你已经彻底改造了三重商店。我认为这是一个常见的事情,因为我们遵循数据库灵活性的概念来达到其自然结论。三重存储在关系数据库系统中的效率往往相当低,但是有专门为它们设计的系统。

http://en.wikipedia.org/wiki/Triplestore

在您所谈论的音阶上,您的表现可能是可以接受的,但如果没有专门的数据库,它们通常不能很好地扩展。

答案 2 :(得分:2)

在我看来,实现这种完全可扩展模型的最佳方法是使用EAV(实体,属性,值)。它基本上是一种将无模式非关系数据库引入SQL的方法。您可以在维基百科上阅读更多关于它的信息,http://en.wikipedia.org/wiki/Entity-attribute-value_model但是在django中更好的实现之一来自EveryBlock代码库。希望这是一个帮助!

http://github.com/brosner/everyblock_code/blob/master/ebpub/ebpub/db/models.py

答案 3 :(得分:1)

您可能会对

http://github.com/tuttle/django-expando感兴趣。

答案 4 :(得分:0)

当我有一个可以由用户完全自定义的对象时,我在模型上创建了一个字段,该字段在列中包含一些JSON。然后,您可以在需要使用或保存时来回序列化。

但是,它确实使得在SQL查询中使用数据变得更加困难。