【问题标题】:Defining django queryset with Q objects with foreign key使用带有外键的 Q 对象定义 django 查询集
【发布时间】: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 查询

标签: django django-queryset django-q


【解决方案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)
    

    【讨论】:

      猜你喜欢
      • 2010-12-27
      • 2015-08-19
      • 2013-12-11
      • 2014-02-06
      • 2015-07-15
      • 1970-01-01
      • 2016-03-31
      • 2018-07-06
      相关资源
      最近更新 更多