如何查询满足多个要求的单个实例的django m2m?

时间:2015-10-22 20:43:51

标签: python django django-orm

为了举例,我有以下Django模型:

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

class Book(models.Model):
    name = models.CharField(max_length=30)
    authors = models.ManyToManyField(Author)

(因为书籍经常有多位作者,作者经常会写多本书)

现在说我有一份作者列表'名称为元组:

author_list = [('clarke', 'arthur'), ('herbert', 'frank'), ('asimov', 'isaac')]

有没有办法查询authors m2m字段至少有一个Author实例满足

的所有图书
author.last_name = pair[0]
author.first_name = pair[1]

对于author_list中的某些对?即至少由一个给定的作者列表中的一个提供所有书籍?

I *想*写的查询如下所示:

Book.objects.filter(
    authors__first_name__in=[pair[1] for pair in author_list],
    authors__last_name__in=[pair[0] for pair in author_list]
)

但这不起作用,因为所有的排列(Arthur Herbert,Frank Asimov,Isaac Clarke等等)都是允许的。但我不确定怎么说,基本上:

'选择所有 作者的书籍,同时满足这两件事。'

或者真的:

'选择所有拥有 作者的图书,其一对(last_name,first_name)位于此元组列表中。'

有没有一种干净的方式在django中进行搜索?

3 个答案:

答案 0 :(得分:1)

我认为您可以使用q对象构建查询

Q(last_name=pair[0], first_name=pair[1]) | Q(last_name=pair2[0], first_name=pair2[1])

以上查询应该生成姓氏为clark且名字为arthur的书籍,或者last_name herbert和first_name frank。

关于如何动态执行此操作有很多答案:

How to dynamically compose an OR query filter in Django?

你可能不得不扭动查询并检查django生成的查询以验证它是你想要的

答案 1 :(得分:1)

好的我觉得这很有效:

query = []
for last_name, first_name in author_list:
    query.append(Q(authors__last_name=last_name, authors__first_name=first_name))
query = reduce(operator.or_, query)
Book.objects.filter(query)

但如果你看到更好的东西,请仍然回答!

答案 2 :(得分:1)

你可以build a query using Q objects.

根据您的回答,但不使用reduceoperator

query = Q()
for last_name, first_name in author_list:
    Q |= Q(authors__last_name=last_name, authors__first_name=first_name)
Book.objects.filter(query)