Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django中数据非规范化的最佳方法?_Python_Mysql_Django - Fatal编程技术网

Python Django中数据非规范化的最佳方法?

Python Django中数据非规范化的最佳方法?,python,mysql,django,Python,Mysql,Django,我正在开发一个简单的web应用程序,存储一些非规范化数据非常有意义 想象一下,一个跟踪评论的博客平台,BlogEntry模型有一个我想保持最新的CommentCount字段 一种方法是使用Django信号 另一种方法是在我的代码中直接放置钩子,创建和销毁注释对象,以同步调用BlogEntry上的一些方法来增加/减少注释计数 我想还有其他的pythonic方法可以通过装饰师或其他巫毒来实现这一点 Django中反规范化的标准设计模式是什么?实际上,如果出现错误,您还必须编写一致性检查程序和数据修正

我正在开发一个简单的web应用程序,存储一些非规范化数据非常有意义

想象一下,一个跟踪评论的博客平台,BlogEntry模型有一个我想保持最新的CommentCount字段

一种方法是使用Django信号

另一种方法是在我的代码中直接放置钩子,创建和销毁注释对象,以同步调用BlogEntry上的一些方法来增加/减少注释计数

我想还有其他的pythonic方法可以通过装饰师或其他巫毒来实现这一点


Django中反规范化的标准设计模式是什么?实际上,如果出现错误,您还必须编写一致性检查程序和数据修正程序吗?

为什么不使用计数方法获取注释集并查找元素数:

然后可以将其传递到模板中

或者,也可以在模板本身中执行以下操作:

{{ blog_entry.comment_set.count }}

获取评论的数量。

第一次进近信号的优点是可以消除模型之间的耦合。 然而,信号在某种程度上更难维护,因为至少在我看来,依赖关系不那么明确。 如果注释计数的正确性不是那么重要,您还可以考虑一个cron作业,它将每n分钟更新一次

然而,无论解决方案如何,非规范化将使维护更加困难;出于这个原因,我会尽量避免它,而改为使用缓存或其他技术-例如,在模板中使用with comments.count as cnt可能会大大提高性能。
然后,如果其他一切都失败了,并且只有在这种情况下,考虑什么可能是解决特定问题的最佳方法。

Django有经理

使用自定义管理器创建和维护FK关系

管理器可以在更新子项集时更新计数

如果不想定制管理器,只需扩展save方法即可。您要对计数和总和进行非规范化处理的所有操作都可以在save中完成


你不需要信号。只需扩展save。

我发现它很有用。它使用数据库级触发器而不是信号,但据我所知,也有基于不同方法的分支。

Django提供了一种非常好、高效但不太为人所知的反规范化替代方法

它将节省许多代码行,而且速度非常慢,因为您在同一个SQL查询中检索计数

我假设你有这些课程:

class BlogEntry(models.Model):
     title = models.CharField()
     ...


class Comment(models.Model):
     body = models.TextField()
     blog_entry = models.ForeignKey(BlogEntry)
在your views.py中,使用:

每个BlogEntry都有一个额外的字段,其中包含评论数,以及BlobEntry的其余字段

您也可以在模板中使用此额外字段:

{% for blog_entry in blog_entries %}
  {{ blog_entry.title }} has {{ blog_entry.count }} comments!
{% endfor %}

这不仅可以节省您的编码和维护时间,而且非常有效。查询只需稍长的时间即可执行。

每次我调用count时,它都会从注释中选择count1,其中。。。当有大量评论时,这将导致性能问题。有多少人在你的博客上留言?我了解数据规范化和非规范化的细节,但在很多情况下,非规范化数据可以极大地提高查询性能,这就是我为什么要考虑它的原因。我的注释计数示例是合成的,但对于任何非规范化建议都是一个很好的示例。缓存是一个好主意,我将开始思考…缓存将具有所有非规范化维护问题,即保持缓存最新,在适当时使缓存数据无效。更糟糕的是,这样做并不会让您受益于Django ORM设备。我将投票支持@gorsky建议的django denorm——如果您有它所涵盖的一个非规范化用例,它将为您解决所有维护问题。您知道这种风格的好例子吗?我很惊讶Django文档或Django书籍根本没有提到反规范化方法……说真的,对于服务器来说,在正确索引的行上执行计数操作是微不足道的,特别是当您只使用简单的WHERE条件时,例如WHERE comment.blog_id=。在这种情况下,请确保对blog_id列进行了索引。如果,比方说,你有一个博客id,在索引上发布,复合索引也可以;数据库引擎通常足够聪明,可以从这些数据中推断出部分索引。+1对于django denorm,它是一个非常好而且简单的系统,而不是手动将您自己的信号和重写的方法拼凑在一起。我研究了django denorm源代码。我看不到用于删除操作的挂钩。。。你知道他们是否得到管理吗?在我看来,似乎没有使用数据库触发器,但这也不错。普通表由模型字段中的后期保存方法更新。
from django.db.models import Count

def blog_entry_list(Request):
    blog_entries = BlogEntry.objects.annotate(count=Count('comment_set')).all()
    ...
{% for blog_entry in blog_entries %}
  {{ blog_entry.title }} has {{ blog_entry.count }} comments!
{% endfor %}