Создание сайта на Django: Урок 14, фильтрация статей по категориям
avatar
7 | (offline)
❤️‍🔥Notehunter Developer
Добавлено:
Категория: Руководства «Django»
Комментариев: 0

Фильтрация статей по категориям (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 категории статьи. 

Фильтрация по категориям выглядит следующим образом:

Комментарии к статье 0
Комментариев нет
Форма добавления комментария (необходима регистрация)