Фильтр чекбоксами на сайте Django
Имеется: Сайт с книгами. Модели книг, авторов. View с выводом данных в качестве списка (ListView)
Нужно: Организовать чекбоксы для фильтрации книг по авторам или по категориям (жанрам). Каждый чекбокс соответствует одному автору или одной категории (жанру)
Код: models.py
class Book(models.Model):
""" Модель, представляющая книги """
title = models.CharField(max_length=200)
author = models.ForeignKey('Author', on_delete=models.SET_NULL, null=True)
# ForeignKey использую, потому что книга может иметь только одного автора, но автор много книг
summary = models.TextField(max_length=1000, help_text='Введите краткое описание книги')
isbn = models.CharField('ISBN', max_length=13, help_text='13 символова <a href="https://www.isbn-international.org/content/what-isbn">ISBN номера</a> книги')
genre = models.ManyToManyField(Genre, help_text='Выберите жанр книги')
def __str__(self):
return self.title
def get_absolute_url(self):
""" Возвращает URL для доступа к странице книги"""
return reverse('book-detail', args=[str(self.id)])
def display_genre(self):
return ', '.join([genre.name for genre in self.genre.all()[:3]])
class Author(models.Model):
""" Модель представляет автора """
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
date_of_birth = models.DateField(null=True, blank=True)
date_of_death = models.DateField('Died', null=True, blank=True)
def get_absolute_url(self):
""" Возвращает url для доступа к странице автора"""
return reverse('author-detail', args=[str(self.id)])
def __str__(self):
return '{}, {}'.format(self.last_name, self.first_name)
class Genre(models.Model):
""" Модель, представляющая жанры книг"""
name = models.CharField(max_length=200, help_text="Введите жанр книги")
def __str__(self):
return self.name
views.py
class BookListView(generic.ListView):
model = Book
paginate_by = 15
Ответы (1 шт):
Фильтр по жанру например можно сделать так. Во views.py в класс добавьте :
from django.views.generic import ListView
class BookListView(ListView):
model = Book
paginate_by = 15
class Genre:
"""Жанры"""
def get_genres(self):
return Genre.objects.all()
class FilterBooksView(Genre, ListView):
paginate_by = 5
def get_queryset(self):
queryset = Book.objects.filter(genre__in=self.request.GET.getlist("genre")).distinct()
return queryset
ну и в шаблоне страницы
<form action="{% url 'filter' %}" method="get" name="filter">
<h1 >Жанры</h3>
{% for genre in view.get_genres %}
<li>
<input type="checkbox" class="checked" name="genre" value="{{ genre.id }}">
<span>{{ genre.name }}</span>
</li>
{% endfor %}
</ul>
</div>
<button type="submit">Найти</button>
</form>
urls.py
urlpatterns = [
......
path("filter/", views.FilterBooksView.as_view(), name='filter'),
......
]
если что не понятно, спрашивайте.
Если надо будет добавить еще n-ое количество фильтров
добавляете представления в класс Gener (Можете переименовать для лучшего чтения кода, например если добавить еще и авторов GenerAuthor ).
def get_author(self):
return Author.objects.all()
И в классе поиска изменить queryset на:
queryset = Book.objects.filter(
Q(genre__in=self.request.GET.getlist("genre")) |
Q(first_name__in=self.request.GET.getlist("first_name"))
).distinct()
и добавить from django.db.models import Q
Ну и добавить поля в форму в шаблоне. Единственное что вы наверное зря разбили имя и фамилию автора, я бы объединил для однозначного поиска по автору. Если есть знания ajax то лучше сделать с его использованием .