2017-07-12 193 views
0

我有这些样本数据库模型Django查询比较两个foreignkey字段?

class Book(models.Model): 
    name = CharField() 
    price = IntegerField() 

class Author(models.Model): 
    name = CharField() 
    book = ForeignKey(Book, related_name='authors') 
    type = CharField(choices=('high','medium','low')) 

class Random(models.Model): 
    book = Foreignkey(Book, related_name='randoms') 
    type = CharField(choices=('high','medium','low')) 
    rank = PositiveIntegerField() 

数据库对象: -

  1. B1 =书( 'BOOK1',25)
  2. B2 =书( 'Book2中',30)

  3. 作者( '作者1',B1, '高')

  4. 作者( 'author2',B1, '媒介')
  5. 作者( 'author3',B1, '媒介')
  6. 作者( 'author4',B2, '低')

  7. 作者( 'author5',B2, '低')

  8. 作者( 'author6',B2, '低')

  9. 随机(B1, '高',1)

  10. 随机(B1, '中',2)

  11. 随机(B1, '低',5)
  12. 随机(B2, '低',3)
  13. 随机(B2, '高',0)
  14. 随机(B2, '中',0 )

将会有一个Random模型,其rank表示一个特定类型的书的作者的正确计数。 例如,如果一本书有随机(book,'high',20)。那么这意味着必须有20位作者的high类型。如果有超过或少于20位作者,那么这是一个错误。 我想过滤那些有这种类型的错误的对象Book

这里b1有0个类型为low的作者,但它有Random对象,其中'low'的排名是5。意思是必须有5个类型为low的作者。 b1有错误。 但这并非如此b2

如何过滤这些书籍对象?

回答

0

您可以尝试过滤所有随机对象。然后使用for循环,您可以检查rank和类型作者的数量是否与书籍相同。这是一个代码[未经测试]的相同。您可以使用count()

all_random = Random.objects.all() 
wrong_book=[] 
for random in all_random: 
    if Author.objects.filter(book=random.book,type=random.type).count() != random.rank: 
     wrong_book.append(random.book) 
result= set(wrong_book) 

wrong_book是书籍对象的列表。

+0

任何方法与适当的django查询做到这一点? –

+0

在wrong_book列表中存在重复的书对象错误。所以我们应该使用set而不是list。 –

+0

@HiteshGarg感谢您的更正请参阅我的编辑。 – badiya

0

最后,我想出了一个用Django ORM来完成它的方法。

high_queryset = Books.objects.annotate(t=Case(When(authors__option='high', 
          then=Count('authors', distinct=True)), default=Value('0'),output_field=PositiveIntegerField(),),) \ 
          .filter(Q(randoms__option='high') & ~Q(t=F('randoms__value'))) 

medium_queryset = Books.objects.annotate(t=Case(When(authors__option='medium', 
          then=Count('authors', distinct=True)), default=Value('0'),output_field=PositiveIntegerField(),),) \ 
          .filter(Q(randoms__option='medium') & ~Q(t=F('randoms__value'))) 

low_queryset = Books.objects.annotate(t=Case(When(authors__option='low', 
          then=Count('authors', distinct=True)), default=Value('0'),output_field=PositiveIntegerField(),),) \ 
          .filter(Q(randoms__option='low') & ~Q(t=F('randoms__value'))) 


final_queryset = (high_queryset | medium_queryset | low_queryset).distinct()