如何使 Django 注释在“用户”字段上使用 select_lated() ?

2024-01-04

我在用着Django 评论框架 https://docs.djangoproject.com/en/dev/ref/contrib/comments/。所有评论均由经过身份验证的用户发布。在评论附近,我使用显示一些用户个人资料信息{{ comment.user.get_profile }}

{# custom comment list templates #}
<dl id="comments">
  {% for comment in comment_list %}
    <dt id="c{{ comment.id }}">
        {{ comment.submit_date }} - {{ comment.user.get_profile.display_name }}
    </dt>
    <dd>
        <p>{{ comment.comment }}</p>
    </dd>
  {% endfor %}
</dl>

问题是django的评论查询不使用select_related()对于 100 条评论,我在数据库中得到了 101 条点击。

有没有一种方法可以让 django 评论框架一次性为每个评论选择用户配置文件?


我测试了使用默认值渲染对象的 100 条注释{% get_comment_list %}tag 和 django 做了 200 个评论相关的查询来列出评论+用户+个人资料,因为......

  1. Comment.__unicode__实际上打电话Comment.user if a user_id存在。 +1 查询
  2. get_profile+1 查询

Ouch!

我从大约 25 毫秒内的 203 个查询减少到大约 2 毫秒内的 3 个查询。

自己填充comment_list

I would 强烈建议建设comment_list QuerySet自己使用适当的select_related()来电。如果经常使用,请创建一个从其他视图调用的实用函数。

def get_comments_with_user_and_profile(obj):
    content_type =ContentType.objects.get_for_model(obj)
    return (Comment.objects
        .filter(content_type=content_type, object_pk=obj.id)
        .select_related('user__profile'))

如果您希望整个框架都以这种方式运行...您必须进行猴子修补。

这不是我会轻易做的事。还有其他方法可以解决这个特定问题,但您确实“一口气”问了。

把这个放在你的某个地方INSTALLED_APPS models.py文件。我其实有一个monkey_patch用于修改的应用程序django.contrib.auth.User.username长度等(这是与这里不同的最后手段)。

from django.contrib.comments.models import Comment
from django.contrib.comments.managers import CommentManager

class CommentManager(CommentManager):
    def get_query_set(self):
        return (super(CommentManager, self)
            .get_query_set()
            .select_related('user__profile'))
Comment.add_to_class('objects', CommentManager())

有关配置文件和 select_lated() 的问题

请注意,您的UserProfile类需要一个OneToOneField to User with a related_name等于你传递给的select_related()。在我的例子中是profile并且你需要 django 1.2+。我记得以前偶然发现过这一点。

class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='profile') 
    # example to use User.objects.select_related('profile')
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使 Django 注释在“用户”字段上使用 select_lated() ? 的相关文章

随机推荐