Как сгруппировать данные модели, основанные на другой модели, и сделать пагинацию в django?

У меня есть две модели:

  1. Category - Zero or multiple books can be in one category
  2. 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>
Вернуться на верх