假设我们将Django模型定义如下:
class Tag(models.Model):
name=models.CharField(unique=True,max_length=50)
class Article(models.Model):
title=models.CharField(max_length=100)
text=models.TextField()
tag = models.ManyToManyField(Tag)
我们有一个标签列表:
tag_list = ['tag1','tag2','tag3']
目标是选择包含tag_list
所有标签的文章。这个question显示了一种在顺序添加过滤条件的情况下实现此目的的方法:
articles = Articles.objects.filter(Q(tag__name=tag_list[0])).filter(Q(tag__name=tag_list[1])).filter(Q(tag__name=tag_list[2]))
但我们需要动态添加条件。以下查询不起作用:
qlist=[]
for tag in tag_list:
qlist.append(Q(tag__name=tag))
articles = Articles.objects.filter(reduce(operator.and_, qlist))
我最终查询了列表中至少有一个标签的文章,然后手动过滤查询结果:
qlist=[]
qlist.append(Q(tag__name__in=tag_list))
articles = Articles.objects.filter(reduce(operator.and_, qlist)).distinct()
for article in articles:
article_tag_list=[]
for tag in article.tag.all():
article_tag_list.append(tag.name)
if set(tag_list).issubset(set(article_tag_list)):
...
有没有办法动态添加ManyToManyField
的查询条件?
答案 0 :(得分:0)
试试这个:
q_objects = Q()
for tag in tag_list:
q_objects &= Q(tag__name=tag)
articles = Articles.objects.filter(q_objects)
我上面使用了多次这种模式,它总是对我有用。
更新:虽然一般来说此方法有效,但它不适用于此问题。上面的代码要求所有条件对于单个相关对象都是真的。在这种情况下,这意味着必须有一个具有三个不同名称的单个标签,这显然是荒谬的。
这是最终为OP工作的代码:
for tag in tag_list:
articles = articles.filter(tag__name=tag)
Django docs provide a detailed explanation将多个规则放在一个filter()
中并将它们放在多个filter()
中(当涉及查询多值关系时)之间的区别。