Django查询比较两个foreignkey字段?

时间:2017-07-12 16:46:55

标签: django

我有这些示例数据库模型

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 = Book('book1',25)
  2. b2 = Book('book2',30)

  3. 作者('author1',b1,'high')

  4. 作者('author2',b1,'medium')
  5. 作者('author3',b1,'medium')
  6. 作者('author4',b2,'low')

  7. 作者('author5',b2,'low')

  8. 作者('author6',b2,'low')

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

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

  11. 随机(b1,'low',5)
  12. 随机(b2,'low',3)
  13. 随机(b2,'高',0)
  14. 随机(b2,'中',0)
  15. 将会有一个Random模型,其rank表示特定类型图书的作者的正确数量。 例如,如果一本书有随机(书,'高',20)。那意味着必须有20位作者high。如果有超过或少于20个作者,那么这是一个错误。 我想过滤那些有这种错误的Book个对象。

    这里b1没有类型=低的作者,但是它有随机对象,其中'低'的等级是5.意味着必须有5个低类型的作者。 b1有错误。 但这不是b2

    的情况

    如何过滤这些Book对象?

2 个答案:

答案 0 :(得分: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是书籍对象的列表。

答案 1 :(得分: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()