我想采用Project.objects.all()的Queryset并过滤包含用户所选属性列表的所有项目。Django Queryset通过Manytomany过滤pk列表
models.py
class Attribute(models.Model):
title = models.CharField(max_length=20)
class Project(models.Model):
title = models.CharField(max_length=30)
attributes = models.ManyToManyField(Attribute)
## For the sake of this example, there are two Projects and two Attributes
## Project1 is associated to attr1 and attr2
## Project2 is associated to attr1
我发现这一点:Django Docs Complex Lookups with Q objects并通过其他计算器得到的答案在这里:
非工作代码(self.multiselect是PKS的列表)
query = reduce(operator.and_, (Q(attributes__pk=selection) for selection in self.multiselect))
return queryset.filter(query)
但是,此代码提供了一个空的Queryset。我开始在交互式shell中进行一些测试以确定哪里出了问题。
测试
queryset = Project.objects.all()
########## & is not working
queryset.filter(Q(attributes__pk=1) & Q(attributes__pk=2))
# []
########## | has no issues
queryset.filter(Q(attributes__pk=1) | Q(attributes__pk=2))
# [<Project: Project1>, <Project: Project2>, <Project: Project1>]
########## & works on Project but not on Attribute
queryset.filter(Q(title__contains="Project") & Q(title__contains="1"))
# [<Project: Project1>]
好像&不工作的项目和属性之间的多对多关系。是否有这个原因,是否有一个简单的修复代码,将使其正常工作?任何帮助,将不胜感激。
作为一个侧面说明,减少函数返回正是它应该
########## Reduce does not create an issue
Q(attributes__pk=1) & Q(attributes__pk=2)
# <Q: (AND: ('attributes__pk', 1), ('attributes__pk', 2))>
reduce(operator.and_, [Q(attributes__pk=selection) for selection in [1,2]])
# <Q: (AND: ('attributes__pk', 1), ('attributes__pk', 2))>
是啊。我试图找出背后的数学,但它似乎产生了所需的输出。谢谢<3编辑:我想必须有'过滤器','Q'和'&'的错误,因为否定给我的一切,但我的期望输出,所以你会认为,非否定形式会给我我预期的结果。很好,赶上^^ – pieisawesome102
很高兴帮助你。 –