【问题标题】:Django query to compare two foreignkey fields?Django查询比较两个外键字段?
【发布时间】:2017-12-17 05:19:02
【问题描述】:

我有这些示例数据库模型

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, 'high', 1)

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

  11. 随机(b1,'低',5)
  12. 随机(b2,'低',3)
  13. 随机(b2, 'high', 0)
  14. 随机(b2, 'medium', 0)

将有一个Random 模型,其rank 代表特定类型书籍的作者的正确数量。 例如,如果一本书有 Random(book, 'high', 20)。那么这意味着必须有 20 个作者类型为high。如果作者多于或少于 20 人,则为错误。 我想过滤那些出现此类错误的Book 对象。

这里b1 有零个作者类型=低,但它有随机对象,其中“低”等级为 5。意味着必须有 5 个低类型作者。 b1 有错误。 但这不是b2的情况

如何过滤这些 Book 对象?

【问题讨论】:

    标签: django


    【解决方案1】:

    您可以尝试过滤所有随机对象。然后使用 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 是书籍对象的列表。

    【讨论】:

    • 有什么方法可以通过适当的 django 查询来做到这一点?
    • error_book 列表中存在重复书籍对象的错误。所以我们应该在这里使用 set 而不是 list。
    【解决方案2】:

    最后,我找到了一种使用 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()
    

    【讨论】:

      猜你喜欢
      • 2017-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多