Django База [2023]: Реализация похожих статей по тегам #31
В данной статье будет рассмотрено создание системы, которая позволяет находить похожие статьи по тегам и выводить рядом с основной статьей. Эта система предоставляет дополнительную навигацию на сайте и может помочь удержать посетителей на сайте, особенно если они пришли через поисковую систему.
Если вы хотите выразить благодарность автору сайта, статей и курса по Django, вы можете сделать это по ссылке ниже:
Преимущество похожих статей:
- Дополнительная перелинковка по сайту.
- Инструмент удержания посетителей.
- Заинтересовать посетителей и сформировать базу постоянных посетителей.
Перед реализацией вы должны уже настроить систему тегов, которую мы рассмотрели в данном уроке
Реализация во views.py
Поиск похожих статей по тегам мы будем реализовывать в нашем представлении ArticleDetailView из файла views.py нашего приложения blog, для этого модернизируем его, добавив метод get_similar_articles()
:
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:
<!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:
{% 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 %}
Проверка похожих статей на сайте
Отлично, все работает так, как мы хотели.