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

Реализация похожих статей будет происходит в представлении ArticleDetailView:

modules/blog/views/articles.py


class ArticleDetailView(DetailView):
	"""
    Представление детальной статьи
    """
    model = Article
    template_name = 'modules/blog/articles/article-detail.html'
    context_object_name = 'article'
    queryset = Article.custom.detail()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = self.object.title
        context['form'] = CommentCreateForm
        return context

Модернизируем следующим образом:

modules/blog/views/articles.py

import random
from django.db.models import Count
 
class ArticleDetailView(DetailView):
    """
    Контроллер детальной статьи
    """
    model = Article
    template_name = 'modules/blog/articles/article-detail.html'
    context_object_name = 'article'

    def get_queryset(self):
        queryset = Article.custom.detail()
        return queryset

    def get_similar_articles(self, obj):
        article_tags_ids = obj.tags.values_list('id', flat=True)
        similar_articles = Article.objects.filter(tags__in=article_tags_ids).exclude(id=obj.id)
        similar_articles = similar_articles.annotate(related_tags=Count('tags')).order_by('-related_tags')
        similar_articles_list = [similar for similar in similar_articles.all()]
        random.shuffle(similar_articles_list)
        return similar_articles_list[0:6]

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = f'{self.object.title}'
        context['form'] = CommentCreateForm
        context['similar_articles'] = self.get_similar_articles(self.object)
        return context

Пояснения:

  • Через функцию get_similar_articles мы получаем список тегов, далее мы добавляем фильтр к статьям, получая статьи по тегам из просматриваемой статьи, и исключая статью в которой мы находимся.
  • Далее мы сортируем статьи по тегам, и все это рандомизируем.
  • Возвращаем в контекст как выполненную функцию и выводим в шаблон

Я подправлю main.html для вывода похожих новостей в sidebar'е.

templates/main.html

<!DOCTYPE html>
<html lang="ru">
<head>
    {% load static %}
    <meta charset="UTF-8">
    <title>{{ title }}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- INCLUDE CSS -->
    <link href="{% static 'plugins/bootstrap-5.2.0-dist/css/bootstrap.min.css' %}" type="text/css" rel="stylesheet">
</head>
<body>
<div class="container">
    {% include 'navbar.html' %}
    <div class="row">
        <div class="col-md-8">
            {% include 'includes/messages.html' %}
            {% block content %}

            {% endblock %}
            {% include 'pagination.html' %}
        </div>
        <div class="col-md-4">
            {% block sidebar %}
            {% endblock %}
        </div>
    </div>
</div>
<script src="{% static 'plugins/bootstrap-5.2.0-dist/js/bootstrap.bundle.min.js' %}"></script>
<script src="{% static 'custom/js/backend.js' %}"></script>
{% block script %}
{% endblock %}
</body>
</html>

Пояснения:

  • Добавил {% block sidebar %} {% endblock %}

Теперь перейду в article-detail.html и добавлю в созданный блок похожие статьи

templates/modules/blog/articles/article-detail.html

{% extends 'main.html' %}
{% load static %}

{% block content %}
    <div class="card border-0 mb-3">
        <div class="card-body">
            <div class="row">
                <div class="col-md-4">
                    <figure>
                        <img src="{{ article.get_thumbnail }}" width="200" alt="{{ article.title }}">
                    </figure>
                </div>
                <div class="col-md-8">
                     <h5 class="card-title">
                        {{ article.title }}
                    </h5>
                    <small class="card-subtitle">
                        {{ article.created_at }} / {{ article.category }}
                    </small>
                    <div class="card-text">
                        {{ article.full_description }}
                    </div>
                     <hr/>
                      Добавил: <img src="{{ article.author.profile.get_avatar }}" class="rounded-circle" width="26" height="26"/> {{ article.author }}
                    <hr/>
                    <strong>Теги записи</strong>: {% for tag in article.tags.all %} <a href="{% url 'article-list-by-tags' tag.slug %}">{{ tag }}</a>, {% endfor %}
                    <hr/>
                    {% if article.reason %}{{ article.reason }} / обновил: {{ article.updated_by }}{% endif %}
                </div>
            </div>
        </div>
    </div>
    <div class="card border-0">
        <div class="card-body">
            <h5 class="card-title">
                Комментарии
            </h5>
            {% include 'modules/blog/comments/comments-list.html' %}
        </div>
    </div>
{% endblock %}

{% block sidebar %}
<div class="card mb-2 border-0">
    <div class="card-body">
        <div class="card-title">
           Похожие статьи
        </div>
        <div class="card-text">
            <ul class="similar-articles">
                {% for sim_article in similar_articles %}
                    <li><a href="{{ sim_article.get_absolute_url }}">{{ sim_article.title }}</a></li>
                {% endfor %}
            </ul>
        </div>
    </div>
</div>
{% endblock %}

{% block script %}
<script src="{% static 'custom/js/article-detail.js' %}"></script>
{% endblock %}

Проверяем в шаблоне:

Отлично. Мы добавили похожие статьи как и на моем сайте notehunter.net!

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