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

Posted

技术标签:

【中文标题】如何在 Django 模型中存储任意名称/值键对?【英文标题】:How to store arbitrary name/value key pairs in a Django model? 【发布时间】:2010-12-11 02:12:29 【问题描述】:

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

类小部件(Models.model): widget_owner = models.ForeignKey(auth.User) val1 = 模型.CharField() val2 = 模型.CharField() ... val568 = ...

我想通过让我的用户指定自定义数据字段来将更多数据填充到这个小部件中。这样做的明智方法是什么?将名称/值对存储在用户可以指定其他“小部件字段”的位置是个好主意吗?我的伪想法如下:

data_types = ('free_text', 'date', 'integer', 'price') 类 CustomWidgetField(models.Model) 所有者 = ForeignKey(auth.User) field_title = models.CharField(auth.User) field_value_type = models.CharField(choices = data_types) 类 CustomWidgetValue(models.Model) field_type = ForeignKey(CustomWidgetField) 小部件 = ForeignKey(小部件) 值 = 模型.TextField()

所以我想让每个用户构建一种新类型的数据字段,该字段将应用于他们的所有小部件,然后为每个小部件中的每个自定义字段指定值。我可能不得不对这些自定义字段进行过滤/搜索,就像在本地字段上一样(我认为这比在本地字段上操作要慢得多。)但是规模是每个小部件有几十个自定义字段和每个用户的库存中只有几千个小部件。我也可以将自定义字段上的大部分搜索/过滤批处理到后端脚本中(也许。)

【问题讨论】:

【参考方案1】:

考虑用序列化的 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

【讨论】:

只要您不需要根据自定义属性的值进行排序或过滤,此解决方案可能会比 WidgetField 和 WidgetValue 模型更少麻烦(并且性能更好)。可以通过使 props 成为在加载/保存时自动序列化和反序列化自身的自定义字段类型来清理它。【参考方案2】:

看来您已经彻底改造了三重商店。我认为这是很普遍的事情,因为我们遵循数据库灵活性的想法来自然得出结论。三重存储在关系数据库系统中往往效率相当低,但有专门为它们设计的系统。

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

在您所说的规模上,您的性能可能是可以接受的,但如果没有专门的数据库,它们通常不能很好地扩展。

【讨论】:

同意。您可能应该考虑使用 Redland 库或 rdflib (code.google.com/p/rdflib/wiki/IntroStore) 之类的东西,而不是 django 的 db 层。这样做的真正好处在于使用专门的查询语言,例如 SPARQL。【参考方案3】:

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

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

【讨论】:

+1,第一个***链接非常有帮助,它提供了这个常见问题/解决方案空间的历史和命名 - 帮助人们意识到这根本不是一个新领域。第二个链接目前是 404'ing。 请注意,至少有两个 Django 应用程序提供 EAV:eav-django 和 django-eav。前者位于bitbucket.org/neithere/eav-django,其作者仍在积极参与其中。【参考方案4】:

http://github.com/tuttle/django-expando 您可能会感兴趣。

【讨论】:

好像死了。最后一次提交是在 2009 年左右,对于现在访问此答案的任何人... 过时了!最后一次提交是在 2009 年左右【参考方案5】:

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

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

【讨论】:

以上是关于如何在 Django 模型中存储任意名称/值键对?的主要内容,如果未能解决你的问题,请参考以下文章

Django 的唯一外键对

查找存储在数组中的对象值键内的单词

django表单存储模型的下拉列表

如何使用 django rest 框架在模板中获取模型选择字段名称而不是 id

如何在 Django 模型中存储电话号码?

如何获取模型的名称或 Django 对象的内容类型?