Django База [2023]: Реализация похожих статей по тегам #31
Django

Django База [2023]: Реализация похожих статей по тегам #31

Razilator

В данной статье будет рассмотрено создание системы, которая позволяет находить похожие статьи по тегам и выводить рядом с основной статьей. Эта система предоставляет дополнительную навигацию на сайте и может помочь удержать посетителей на сайте, особенно если они пришли через поисковую систему.

Преимущество похожих статей:

  • Дополнительная перелинковка по сайту.
  • Инструмент удержания посетителей.
  • Заинтересовать посетителей и сформировать базу постоянных посетителей.

Перед реализацией вы должны уже настроить систему тегов, которую мы рассмотрели в данном уроке

Реализация во views.py

Поиск похожих статей по тегам мы будем реализовывать в нашем представлении ArticleDetailView из файла views.py нашего приложения blog, для этого модернизируем его, добавив метод get_similar_articles():

blog/views.py
from django.views.generic import DetailView
import random
from django.db.models import Count

from .models import Article
from .forms import CommentCreateForm


class ArticleDetailView(DetailView):
    model = Article
    template_name = 'blog/articles_detail.html'
    context_object_name = 'article'
    queryset = model.objects.detail()

    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 = list(similar_articles.all())
        random.shuffle(similar_articles_list)
        return similar_articles_list[:6]

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

Пояснение к коду выше:

  • Метод get_similar_articles() извлекает список статей, которые имеют общие теги с текущей статьей, и сортирует их по количеству общих тегов. Затем он перемешивает этот список и возвращает первые 6 статей.

  • Метод get_context_data создает контекст шаблона, который включает заголовок статьи, форму создания комментария и список похожих статей, полученных из 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 'bootstrap/css/bootstrap.min.css' %}" type="text/css" rel="stylesheet">
</head>
<body>
    <div class="container">
        {% include 'header.html' %}
        <div class="row">
            <div class="col-8">
            {% include 'includes/messages.html' %}
            {% block content %}{% endblock %}
            {% include 'pagination.html' %}
            </div>
            <div class="col-4">
                {% block sidebar %}{% endblock %}
                {% include 'sidebar.html' %}
            </div>
        </div>
    </div>
<script src="{% static 'bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<script src="{% static 'custom/js/backend.js' %}"></script>
{% block script %}{% endblock %}
</body>
</html>

Далее нам необходимо добавить цикл перебора похожих статей в articles_detail.html:

templates/blog/articles_detail.html
{% extends 'main.html' %}
{% load mptt_tags %}
{% block content %}
<div class="card mb-3 border-0 shadow-sm">
	<div class="row">
		<div class="col-4">
			<img src="{{ article.thumbnail.url }}" class="card-img-top" alt="{{ article.title }}" />
		</div>
		<div class="col-8">
			<div class="card-body">
				<h5>{{ article.title }}</h5>
				<p class="card-text">{{ article.full_description }}</p>
				Категория: <a href="{% url 'articles_by_category' article.category.slug %}">{{ article.category.title }}</a> / Добавил: {{ article.author.username }} / <small>{{ article.time_create }}</small>
			</div>
		</div>
	</div>
	{% if article.tags.all %}
	<div class="card-footer border-0">
		Теги записи: {% for tag in article.tags.all %} <a href="{% url 'articles_by_tags' tag.slug %}">{{ tag }}</a>, {% endfor %}
	</div>
	{% endif %}
</div>
<div class="card border-0">
	<div class="card-body">
		<h5 class="card-title">
			Комментарии
		</h5>
		{% include '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 %}

Проверка похожих статей на сайте

При переходе в статью с тегами мы видим похожие материалы
При переходе в статью с тегами мы видим похожие материалы

Отлично, все работает так, как мы хотели.

;