这些是我的模特:
class Author(models.Model):
name = models.CharField()
class Category(models.Model):
name = models.CharField()
class Book(models.Model):
pages = IntegerField()
author = ForeignKey(Author)
category = ForeignKey(Category)
如何为每位作者选择一本书,该书在特定类别中的页面数最少?然后按页数排序
如果有两本书的页数相同,请选择其中任意一本书。 如果作者没有该类别的书籍,则可以忽略该作者。
谢谢
答案 0 :(得分:0)
您可以使用以下查询:
books = Book.objects.values('author__name')\
.filter(category=selected_category)\
.annotate( min_pages=Min('pages'))\
.order_by('min_pages')
这里是测试方式:
tests.py
class SampleTestCase(TestCase):
def setUp(self) -> None:
a = Author.objects.create(name='a')
b = Author.objects.create(name='b')
c = Author.objects.create(name='c') # Without a book in c1
c1 = Category.objects.create(name='1')
c2 = Category.objects.create(name='2')
Book.objects.create(pages=20, author=a, category=c1)
Book.objects.create(pages=10, author=a, category=c1)
Book.objects.create(pages=15, author=a, category=c1)
Book.objects.create(pages=10, author=a, category=c1)
Book.objects.create(pages=10, author=b, category=c1)
Book.objects.create(pages=5, author=b, category=c1)
Book.objects.create(pages=7, author=b, category=c1)
Book.objects.create(pages=1, author=a, category=c2)
Book.objects.create(pages=1, author=b, category=c2)
Book.objects.create(pages=1, author=c, category=c2)
def test_queryset(self) -> None:
selected_category = Category.objects.get(pk=1)
books = Book.objects.values('author__name')\
.filter(category=selected_category)\
.annotate( min_pages=Min('pages'))\
.order_by('min_pages')
for book in books:
print(book)
# {'author__name': 'b', 'min_pages': 5}
# {'author__name': 'a', 'min_pages': 10}
更新:
如果您需要获取Book
对象-不确定,但是我认为不可能在1个查询中进行。这是您在2中可以做到的方式:
selected_category = Category.objects.get(pk=1)
ids = Book.objects.values('author__pk') \
.filter(category=selected_category) \
.annotate(min_pages=Min('pages')) \
.annotate(id=Min('id'))\
.values('id')\
.order_by('min_pages')
books = Book.objects.filter(pk__in=ids)
for book in books:
print(book)
# Book object (1)
# Book object (5)
答案 1 :(得分:0)
您应该使用django的annotate()子句来确定最少的页面数。然后,您可以将order_by()添加到QuerySet中。 检出:https://docs.djangoproject.com/en/2.2/topics/db/aggregation/
尝试一下:
{{1}}