我有两个模型,名为Article和Label。它们的简化片段如下:
class Label(models.Model):
name = models.CharField(null=True)
class Article(models.Model):
title = models.CharField(null=True)
labels = models.ManyToManyField(Label, related_name='pieces', blank=True)
在查看特定文章时,我希望显示与正在查看的文章具有相似标签的文章,按与正在阅读的文章共享的标签数量排序(例如"类似文章& #34;。)
我正在尝试在数据库中执行此操作但我正在努力寻找一个查询集,它将通过从数据库中提取所有文章并在每个文件上执行for循环来提供与我在Python中所做的相同的功能。他们我正在尝试执行的操作的无效查询尝试如下(Viewed_article是正在查看的文章对象):
articles = Article.objects.all()\
.annotate(
tags_count=Article.objects.filter(F('viewed_article.labels')
).count()).order_by(tags_count)
答案 0 :(得分:2)
您需要使用conditional expressions和一个有点复杂的查询来实现此目的:
from django.db.models import Case, Count, IntegerField, Sum, When
current_labels = viewed_article.labels.all()
similar_articles = Article.objects.filter(labels__in=current_labels).distinct()\
.annotate(
tag_count=Sum(
Case(
When(labels__in=current_labels, then=1),
default=0, output_field=IntegerField()
)
)
).order_by('-tag_count')
发生的事情是:
获取与当前标签共享任何标签的所有文章。需要distinct()
来清除基础JOIN
查询返回的重复项。
使用条件表达式为每篇文章添加注释。在这里,它检查文章是否包含当前文章的每个标签,如果是,则将总和加1。结果是匹配标签的数量。
按匹配标签的数量订购结果。