Фильтрация статей по категориям (ListView) Django
Давайте создадим представление для фильтрации
modules/blog/views/articles.py
class ArticleByCategoryListView(ListView):
model = Article
template_name = 'modules/blog/articles/article-list.html'
context_object_name = 'articles'
category = None
def get_queryset(self):
self.category = Category.objects.get(pk=self.kwargs['pk'])
queryset = Article.objects.all().filter(category_id=self.category.id)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = f'Статьи из категории: {self.category.title}'
return context
Пояснения:
- Название представления говорит само за себя
- template_name - наш шаблон, тот же что и у других представлений
- category - собственная переменная, по которой мы будем работать
- context_object_name - словарь для перебирания в шаблоне
- def get_queryset - метод обработки qs, здесь мы получаем категорию по определенному id, а после мы фильтруем qs статей по категории и возвращаем qs.
- def get_context_data - в этом методе передаем <title></title> категории
Почему я сразу не делаю так?
class ArticleByCategoryListView(ListView):
model = Article
template_name = 'modules/blog/articles/article-list.html'
context_object_name = 'articles'
def get_queryset(self):
queryset = Article.objects.all().filter(category_id=self.kwargs['pk'])
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = f'Статьи из категории: {self.object_list.first().category.title}'
return context
Потому что потом придется повозиться с выводом названия категории в <title></title>, ведь мы можем не только title заполнять, но и другие мета данные для категории на странице со списком статей по категории.
Далее нам нужно настроить urls.py, импортировать наше представление
modules/blog/urls.py
from django.urls import path
from modules.blog.views import ArticleListView, ArticleDetailView, ArticleByCategoryListView
urlpatterns = [
path('', ArticleListView.as_view(), name='article-list'),
path('<str:slug>/', ArticleDetailView.as_view(), name='article-detail'),
path('cat/<int:pk>/<str:slug>/', ArticleByCategoryListView.as_view(), name='article-by-cat') #this,
]
Ещё я передаю slug, но по нему не получаю категорию в get_queryset. Потому что slug может быть одинаковым для подкатегорий, например C++ -> Уроки / Python -> Уроки, в двух случаях уроки будут иметь slug - lesson. А значит, по этому полю смысла фильтровать нет.
Ну а в самом шаблоне article-list.html
templates/modules/blog/articles/article-list.html
{% extends 'main.html' %}
{% block content %}
{% for article in articles %}
<figure>
<img src="{{ article.get_thumbnail }}" width="200" alt="{{ article.title }}">
</figure>
<strong>{{ article.title }}</strong>
<p>{{ article.short_description }}</p>
<p><a href="{% url 'article-by-cat' article.category.pk article.category.slug %}">{{ article.category.title }}</a></p>
<a href="{{ article.get_absolute_url }}">Перейти к полной статье</a>
{% endfor %}
{% endblock %}
Пояснения:
- <a href="{% url 'article-by-cat' article.category.pk article.category.slug %}">{{ article.category.title }}</a> добавил url, где передаю айди категории статьи, slug категории статьи.
Фильтрация по категориям выглядит следующим образом:

