将原始自联接 sql 转换为 Django orm 代码(无内部外键)

Convert a raw self join sql to Django orm code (no internal foreign key)

我有 ArticleTag 模型,通过 ArticleTag 的另一个模型具有多对多关系。我想知道对于给定的标签“健康”,它与文章中的其他标签同时出现了多少次。 (例如,在 4 篇带有“Covid”标签的文章中,在 0 篇带有“Infection”标签的文章中,等等)

我可以使用一些 Where 条件和 Group By 子句在 ArticleTag 上执行自联接并获得所需的结果:

SELECT tag.title, COUNT(*) as co_occurrences
FROM app_articletag as t0
INNER JOIN app_articletag t1 on (t0.article_id = t1.article_id)
INNER JOIN app_tag tag on (tag.id = t1.tag_id)
WHERE t0.tag_id = 43 and t1.tag_id != 43
GROUP BY t1.tag_id, tag.title

但是我想尽可能远离原始查询并使用 Django QuerySet API。

我看过其他关于自连接的帖子,但他们的模型都有一个外键。

这是我的 Django 模型:

class Tag(Model):
    ...

class Article(Model):
    tags = models.ManyToManyField(Tag, through='ArticleTag', through_fields=('article', 'tag'))

class ArticleTag(Model):
    tag = models.ForeignKey(Tag, on_delete=models.CASCADE)) 
    article = models.ForeignKey(Article, on_delete=models.CASCADE))

一种方法是这样的,给定 tHealth 标签:

ArticleTag.objects.values(
    "tag__name"
).annotate(
    articles_with_health=Count(
        "pk", filter=Q(article__articletag__tag=t)
    )
).exclude(tag=t)

这应该 return 结果如下:

[
    {'tag__name': 'Infection', 'articles_with_health': 0}, 
    {'tag__name': 'Covid', 'articles_with_health': 4}
]