希望有人可以帮我解决这个问题。
我正在试图弄清楚是否可以构建一个查询,允许我同时根据ForeignKey字段和ManyToManyField从我的数据库中检索项目。具有挑战性的部分是它需要过滤多个ManyToMany对象。
一个例子有望使这更清楚。这是我的(简化)模型:
class Item(models.Model):
name = models.CharField(max_length=200)
brand = models.ForeignKey(User, related_name='brand')
tags = models.ManyToManyField(Tag, blank=True, null=True)
def __unicode__(self):
return self.name
class Meta:
ordering = ['-id']
class Tag(models.Model):
name = models.CharField(max_length=64, unique=True)
def __unicode__(self):
return self.name
我想构建一个基于两个标准检索项目的查询:
用户关注的用户上传的项目(在模型中称为“品牌”)。因此,例如,如果用户关注Paramount用户帐户,我希望所有商品都在品牌=派拉蒙。
与已保存搜索中的关键字匹配的项目。例如,用户可以制作并保存以下搜索:“80年代喜剧”。在这种情况下,我希望标签中包含“80s”和“喜剧”的所有项目。
现在我知道如何独立构建每个查询。对于#1,它是:
items = Item.objects.filter(brand=brand)
对于#2(基于文档):
items = Item.objects.filter(tags__name='80s').filter(tags__name='comedy')
我的问题是:是否可以将其构建为单个查询,这样我就不必将每个查询转换为列表,加入它们并删除重复项?
挑战似乎是没有办法使用Q对象构建查询,您需要一个项目的manytomany字段(在本例中为tags)来匹配多个值。以下查询:
items = Item.objects.filter(Q(tags__name='80s') & Q(tags__name='comedy'))
不起作用。
(参见:https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships)
先谢谢你的帮助!
答案 0 :(得分:3)
经过大量研究后,我无法找到将其合并为单个查询的方法,因此我最终将我的QuerySet转换为列表并将它们组合在一起。
答案 1 :(得分:2)
Django自动过滤AND。只有在您尝试添加OR时才需要Q
个对象。此外,__in
查询过滤器将为您提供帮助。
假设用户有多个他们喜欢的品牌,并且您想要退回他们喜欢的任何品牌,您应该使用:
`brand__in=brands`
brands
是由someuser.brands.all()
。
同样可以用于您的搜索参数:
`tags__name__in=['80s','comedy']`
这将返回标有“80年代”或“喜剧”的东西。如果你需要两者(标有'80'和'喜剧'的东西),你必须在连续的过滤器中传递每一个:
keywords = ['80s','comedy']
for keyword in keywords:
qs = qs.filter(tags__name=keyword)
P.S。 related_name
值应始终指定相反的关系。你现在的方式会遇到逻辑问题。例如:
brand = models.ForeignKey(User, related_name='brand')
表示somebrand.brand.all()
实际上会返回Item
个对象。它应该是:
brand = models.ForeignKey(User, related_name='items')
然后,您可以使用somebrand.items.all()
获取品牌商品。更有意义。