Как сгруппировать данные модели, основанные на другой модели, и сделать пагинацию в django?
У меня есть две модели:
- Category - Zero or multiple books can be in one category
- Book - A book can have zero or one category
если я сделаю Book.objects.all(), то получу что-то вроде [book11, book10, book9, ...], но я не хочу этого.
Что я хочу, так это что-то вроде:
[
[book11, book2, book1],
[book10],
[book8, book6],
[book7],
[book4, book3],
...
]
Где
- Книги группируются в соответствии с их категорией. Книги, не имеющие категории, также будут включены в список как одноэлементная группа .
- Упорядочение будет происходить в соответствии с созданием книги в обратном порядке
Для лучшего понимания вот структура моей модели:
class Category(models.Model):
name = models.CharField(max_length=50)
class Book(models.Model):
name = models.CharField(max_length=128)
category = models.ForeignKey(Category, on_delete=models.CASCADE,related_name='books', null=True, blank=True)
Этого можно достичь с помощью field lookups из django.
файл_шаблона
<a href="{% url 'myview' category %}"> Detail</a>
urls.py
path('detail/<int:category_id>/',views.myview,name='myview')
views.py
def myview(request,cateory_id):
records = Book.objects.filter(category=category_id)
context={'book_records':records}
return render(request,'appname/anyfile.html',context)
Для выполнения такой группировки в коде Python можно использовать itertools.groupby
from itertools import groupby
qs = Book.objects.order_by('category', '-created_at')
grouped_books = groupby(qs, lambda book: book.category)
for category, books in grouped_books:
print(category)
print(list(books))
Вы также можете сделать это в шаблоне, используя тег regroup
В вашем представлении передайте этот кверисет в контекст шаблона
books = Book.objects.order_by('category', '-created_at')
Ваш шаблон
{% regroup books by category as category_list %}
<ul>
{% for category in category_list %}
<li>{{ category.grouper }}
<ul>
{% for book in category.list %}
<li>{{ book }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>