简体   繁体   English

按外键计数和分组并返回模型django

[英]Count and group by foreign key and return model django

Data Model: 资料模型:

  • Each Library has many Book s 每个Library都有许多Book
  • Each Book may or may not be read by a User dictated by the UserBookReceipt UserBookReceipt指示User可能阅读或不阅读每Book

Objective: 目的:

Given a user, order the libraries by how many books they have read at each library. 对于给定的用户,请按他们在每个图书馆看过多少书来订购图书馆。

Example: 例:

User 1 has read: 用户1已阅读:

  • 2 Books from Library 1 2图书馆书籍1
  • 5 Books from Library 2 5图书馆的书籍2
  • 1 Book from Library 3 1本书来自图书馆3
  • 0 Books from Library 4 0图书馆的书4

We should return the libraries in order of number of books read by User 1 ie: 我们应该按用户1阅读的书籍数量的顺序返回库,即:

Library 2, Library 1, Library 3

Current solution 当前解决方案

libraries = (UserBookReceipt.objects
    .filter(user=user)
    .values('book__library')
    .annotate(rcount=Count('book__library'))
    .order_by('-rcount')
)

Actual output 实际产量

[
    {'book_library': 2, 'rcount': 5}, 
    {'book_library': 1, 'rcount': 2}, 
    {'book_library': 3, 'rcount': 1}
]

Expected output 预期产量

[
    {'book_library': <Library: 2>, 'rcount': 5}, 
    {'book_library': <Library: 1>, 'rcount': 2}, 
    {'book_library': <Library: 3>, 'rcount': 1}
]

The actual output is 90% of what I want, except I want the book_library value to be instances of the django Library model rather than just the library id. 实际输出是我想要的输出的90%,除了我希望book_library值是django Library模型的实例,而不仅仅是库ID。 Otherwise, I have to make another query to retrieve the Library objects which would probably require some inefficient ids__in query . 否则,我必须进行另一个查询来检索Library对象,这可能需要在查询中使用一些低效的ids__in

How can I count and group by the UserBookReceipt.book__library and return the Library model? 如何按UserBookReceipt.book__library计数和分组并返回Library模型?

If I were to do this in SQL the query would look like 如果我要在SQL中执行此操作,查询将如下所示

with rcount_per_lib as (
    select lib.id, count(*) as rcount
    from lib, books, user_book_receipts
    where user_book_receipts.book_id = books.id
        and lib.id = books.lib_id 
        and user_book_receipts.user_id = 1
    group by lib.id)
select lib.*, rcount from rcount_per_lib 
where lib.id = rcount_per_lib.id 
order by rcount

You need to change how you approach the queryset. 您需要更改处理查询集的方式。 Use Library rather than UserBookReceipt . 使用Library而不是UserBookReceipt

libraries = (Library.objects
    .filter(book__userbookreceipt__user=user)
    .annotate(rcount=Count('book__userbookreceipt', distinct=True))
    .order_by('-rcount')
)
[x.rcount for x in libraries]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM