在Django中反规范化数据的最佳方法是什么?
我正在开发一个简单的网页应用,存储一些非规范化的数据是很有必要的。
想象一下一个博客平台,它需要记录评论,而博客文章的模型里有一个“评论数量”的字段,我希望这个字段能够保持最新。
实现这个功能的一种方法是使用Django的信号。
另一种方法是在我的代码中直接添加一些钩子,当创建或删除评论对象时,立即调用一些方法来更新博客文章的评论数量。
我想还有其他更“python风”的方法可以用装饰器或者其他一些技巧来实现。
在Django中,非规范化数据的标准设计模式是什么?在实际操作中,如果出现错误,你还需要写一些一致性检查和数据修复的工具吗?
5 个回答
第一种方法(信号)有个好处,就是可以让模型之间的联系变得不那么紧密。
不过,信号的维护有点麻烦,因为它们之间的依赖关系不太明显(至少在我看来是这样)。
如果评论数量的准确性不是特别重要,你也可以考虑设置一个定时任务,每隔 n 分钟更新一次评论数量。
但是,不管你选择什么解决方案,去规范化会让维护变得更困难; 所以我会尽量 避免这样做,而是使用缓存或其他技术来解决这个问题——比如在模板中使用 with comments.count as cnt
可能会大大提高性能。
最后,如果其他方法都不行,只有在这种情况下,才考虑针对具体问题寻找最佳解决方案。
我发现 django-denorm 这个工具挺有用的。它使用数据库级别的触发器,而不是信号。不过据我所知,还有其他不同的方法可以实现类似的功能。
在Django中,你会用到管理器。
可以使用自定义的管理器来创建和维护外键关系。
这个管理器可以在子项更新时自动更新计数。
如果你不想创建自定义管理器,也可以直接扩展save
方法。你想要做的所有关于去规范化计数和总和的操作都可以在save
中完成。
你不需要使用信号,只需扩展save
方法即可。