I have two models:
- Category - Zero or multiple books can be in one category
- Book - A book can have zero or one category
if I do Book.objects.all()
I'll get something like [book11, book10, book9, ...]
normally but I don't want that.
What I want is something like:
[
[book11, book2, book1],
[book10],
[book8, book6],
[book7],
[book4, book3],
...
]
Where
- Books are grouped according to their category. The books that don't have a category will also include in the list as a single element group
- Ordering would be according to book's creation in reverse
For better understanding here is my model structure:
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)
CodePudding user response:
To do this grouping in Python code you can use 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))
You can also do this in a template using the regroup tag
In your view pass this queryset to your template context
books = Book.objects.order_by('category', '-created_at')
In your template
{% 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>
CodePudding user response:
It can be achieved through field lookups
of django.
template_file
<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)