使用带有外键的 Q 对象定义 django 查询集
Posted
技术标签:
【中文标题】使用带有外键的 Q 对象定义 django 查询集【英文标题】:Defining django queryset with Q objects with foreign key 【发布时间】:2013-02-27 23:12:42 【问题描述】:示例模型:
class Book(models.Model):
title = models.TextField()
class Author(models.Model):
book = models.ForeignKey(Book)
name = models.CharField(max_length=50)
还有一些示例数据:
Book:
id title
1 test111
2 test222
3 test333
4 test444
Author:
book_id name
1 test111
1 test222
2 test222
2 test333
3 test111
3 test333
4 test111
4 test333
我想获取作者姓名包含“111”和“333”的所有书籍(所以所有至少有 2 个作者的书籍:第一个名称为 111,第二个名称为 333)
我可以通过使用链式查询来达到这个目标:
books = Book.objects.filter(author__name__icontains="111").filter(author__name__icontains="333")
返回两本书,id:3 和 4
有没有办法通过使用 Q 对象达到上述目标?
【问题讨论】:
这里模型Book
没有模型 Author
的外键。那么如何使用作者姓名进行过滤呢?
在 shell 上调用 Book.objects.filter(author__name__icontains="111") 时,django 在 (book.id = author.book_id) 上调用带有 INNER JOIN 的 sql 查询
【参考方案1】:
你可以结合reduce和Q,见The power of django’s Q objects帖子。
from django.db.models import Q
import operator
auths = [ "111", "333" ]
query = reduce(operator.and_, [ Q(author__name__icontains=x) for x in auths ] )
books = Book.objects.filter( query )
【讨论】:
【参考方案2】:这个是动态授权列表:
pk_list = qs.values_list('pk', flat=True) # i.e [] or [1, 2, 3]
if len(pk_list) == 0:
Book.objects.none()
else:
q = None
for pk in pk_list:
if q is None:
q = Q(pk=pk)
else:
q = q | Q(pk=pk)
Book.objects.filter(q)
【讨论】:
以上是关于使用带有外键的 Q 对象定义 django 查询集的主要内容,如果未能解决你的问题,请参考以下文章