我有一个固定的数据模型,它有很多数据字段。
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有几十个自定义字段和每个用户的库存中只有几千个小部件。我也可以将自定义字段的大部分搜索/过滤批量转换为后端脚本(可能。)
答案 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)
答案 4 :(得分:0)
当我有一个可以由用户完全自定义的对象时,我在模型上创建了一个字段,该字段在列中包含一些JSON。然后,您可以在需要使用或保存时来回序列化。
但是,它确实使得在SQL查询中使用数据变得更加困难。