【问题标题】:Problem trying to achieve a join using the `comments` contrib in Django尝试在 Django 中使用“comments”contrib 实现连接时出现问题
【发布时间】:2011-02-14 19:24:00
【问题描述】:

我有这个模型,cmets 由django_comments contrib 管理:

class Fortune(models.Model):
    author = models.CharField(max_length=45, blank=False)
    title = models.CharField(max_length=200, blank=False)
    slug = models.SlugField(_('slug'), db_index=True, max_length=255, unique_for_date='pub_date')
    content = models.TextField(blank=False)
    pub_date = models.DateTimeField(_('published date'), db_index=True, default=datetime.now())
    votes = models.IntegerField(default=0)
    comments = generic.GenericRelation(
        Comment,
        content_type_field='content_type',
        object_id_field='object_pk'
    )

我想检索 Fortune 对象,并为每个对象添加一个补充 nb_comments 值,计算它们各自的 cmets 数量;我试试这个查询:

>>> Fortune.objects.annotate(nb_comments=models.Count('comments'))

从外壳:

>>> from django_fortunes.models import Fortune
>>> from django.db.models import Count
>>> Fortune.objects.annotate(nb_comments=Count('comments'))
[<Fortune: My first fortune, from NiKo>, <Fortune: Another One, from Dude>, <Fortune: A funny one, from NiKo>]
>>> from django.db import connection
>>> connection.queries.pop()
{'time': '0.000', 'sql': u'SELECT "django_fortunes_fortune"."id", "django_fortunes_fortune"."author", "django_fortunes_fortune"."title", "django_fortunes_fortune"."slug", "django_fortunes_fortune"."content", "django_fortunes_fortune"."pub_date", "django_fortunes_fortune"."votes", COUNT("django_comments"."id") AS "nb_comments" FROM "django_fortunes_fortune" LEFT OUTER JOIN "django_comments" ON ("django_fortunes_fortune"."id" = "django_comments"."object_pk") GROUP BY "django_fortunes_fortune"."id", "django_fortunes_fortune"."author", "django_fortunes_fortune"."title", "django_fortunes_fortune"."slug", "django_fortunes_fortune"."content", "django_fortunes_fortune"."pub_date", "django_fortunes_fortune"."votes" LIMIT 21'}

以下是格式正确的 sql 查询:

SELECT "django_fortunes_fortune"."id", 
       "django_fortunes_fortune"."author", 
       "django_fortunes_fortune"."title", 
       "django_fortunes_fortune"."slug", 
       "django_fortunes_fortune"."content", 
       "django_fortunes_fortune"."pub_date", 
       "django_fortunes_fortune"."votes", 
       COUNT("django_comments"."id") AS "nb_comments" 
FROM "django_fortunes_fortune" 
LEFT OUTER JOIN "django_comments" 
    ON ("django_fortunes_fortune"."id" = "django_comments"."object_pk") 
GROUP BY "django_fortunes_fortune"."id", 
         "django_fortunes_fortune"."author", 
         "django_fortunes_fortune"."title", 
         "django_fortunes_fortune"."slug", 
         "django_fortunes_fortune"."content", 
         "django_fortunes_fortune"."pub_date", 
         "django_fortunes_fortune"."votes" 
LIMIT 21

你能发现问题吗? Django 不会将django_comments 表与content_type 数据(其中包含对fortune 之一的引用)连接起来。

这是我希望能够使用 ORM 生成的那种查询:

SELECT "django_fortunes_fortune"."id", 
       "django_fortunes_fortune"."author", 
       "django_fortunes_fortune"."title", 
       COUNT("django_comments"."id") AS "nb_comments" 
FROM "django_fortunes_fortune" 
    LEFT OUTER JOIN "django_comments" 
        ON ("django_fortunes_fortune"."id" = "django_comments"."object_pk") 
    LEFT OUTER JOIN "django_content_type" 
        ON ("django_comments"."content_type_id" = "django_content_type"."id") 
GROUP BY "django_fortunes_fortune"."id", 
         "django_fortunes_fortune"."author", 
         "django_fortunes_fortune"."title", 
         "django_fortunes_fortune"."slug", 
         "django_fortunes_fortune"."content", 
         "django_fortunes_fortune"."pub_date", 
         "django_fortunes_fortune"."votes" 
LIMIT 21

但我做不到,因此非常感谢 Django 退伍军人的帮助 :)

提示:我使用的是 Django 1.2-DEV

提前感谢您的帮助。

【问题讨论】:

    标签: python sql django orm django-models


    【解决方案1】:

    为什么要加入内容类型表?原始查询是错误的,但不是因为这个原因。对内容类型的引用是为了识别与 cmets 关联的目标模型 - 但您已经知道这一点,因为您只选择与 Fortune 关联的 cmets。 Django 已经查询了ContentType 模型以获取Fortune 的值,因此只需添加一个WHERE 子句:

    ... WHERE django_comments_comment.content_type_id = xx
    

    您可以通过添加等效的 ORM 来使其正常工作:

    ...filter(comment__content_type=ContentType.objects.get_for_model(Fortune))
    

    虽然 Django 不会自动执行此操作似乎是一个错误。

    【讨论】:

    • 谢谢,通过将comment__content_type 替换为comments__content_type 它可以工作,所以再感谢一次。顺便说一句,正如cyberdelia所说,它确实是bug:/
    • 好吧,对不起,实际上它没有用。我最终得到了不正确的评论计数:/
    【解决方案2】:

    这是 Django 中的一个错误,请参阅票证 #10870。您至少必须等待 Django 1.3 或自己修复它。

    【讨论】:

      【解决方案3】:
      猜你喜欢
      • 1970-01-01
      • 2019-04-05
      • 2020-08-29
      • 2019-05-26
      • 2018-11-16
      • 2022-01-25
      • 2022-11-26
      • 2013-03-27
      • 2021-09-07
      相关资源
      最近更新 更多