Django Queryset过滤器相关字段isnull查找最后一个对象,Book(Loan - Return)

时间:2016-01-04 18:25:19

标签: django django-queryset

我将展示一个模型的示例,并在此讨论该问题。因为用问题描述起来很难。

# Available:
Book.objects.filter(
            Q(loan__isnull=True)|           # Book has never been borrowed           
            Q(loan__return__isnull=False)   # Book has been borrowed but returned
).distinct()
  

预订可用===借书未借出或最后贷款退还书籍

Book

上述过滤器部分正确。

available被退回并再次重新借出时,唯一的问题就出现了。

借书后,它不应该可用,但会以loan__return__isnull=False的形式返回上述查询集,因为该特定图书仍然存在Loan

我无法在此类查询中找出更好的方法。我们怎样才能使这样简单的查询起作用?

可能的解决方案

我能想到的解决方案非常难看。它涉及多个单独的查询。但大致步骤如下:

  1. Book查询最后 Loan组。 (已借书)
  2. Return为空的过滤器Book。 (预订尚未归还)
  3. 查询Loan,匹配满足条件2的所有Book
  4. 查询Loan/items/userid/new为空。 (书从来没有借过)
  5. 注意(3& 4组合在一起作为一个查询)

2 个答案:

答案 0 :(得分:1)

Book.objects.filter(
        Q(loan__isnull=True) # Book has never been borrowed 
        | ( Q(loan__return__isnull=True) & Q(loan__isnull=False)) ) # Book has been borrowed but not returned
        | Q(loan__return__isnull=False) # Book has been borrowed but returned
).distinct()

答案 1 :(得分:1)

解决此问题的不同方法。

  

它解决了我的问题,但我无法证明它的正确性。

在这种方法中,我将使用CountLoan中的Return

  • 如果Count(Loan)==Count(Return),则Book可用
  • 其他Book不可用

示例代码

# Available Books
Book.objects.annotate(
    loan_count=Count('loan'),
    return_count=Count('loan__return')
).filter(Q(issue_count=F('return_count')))

# Unavailable Books
Book.objects.annotate(
    loan_count=Count('loan'),
    return_count=Count('loan__return')
).exclude(Q(issue_count=F('return_count')))