Получение записей по сходству

Теперь, когда у нас есть теги для записей блога, мы можем сделать много интересных вещей с ними. С помощью тегов можно очень хорошо классифицировать записи блога. Для постов по сходным темам будет иметься несколько общих тегов. Мы собираемся построить функционал для отображения схожих постов по количеству тегов, которые они разделяют. Таким образом, когда пользователь читает пост, мы можем предложить ему прочитать другие похожие посты.

Для получения схожих записей для конкретного поста необходимо:

  • Извлечь все теги для текущей записи.
  • Получить все посты, помеченные любым из этих тегов.
  • Исключить из этого списка текущую запись, с тем чтобы ее же не рекомендовать.
  • Выдать результаты по количеству тегов, общих для текущей записи.
  • В случае двух или более записей с одинаковым числом тегов рекомендуется использовать самую последнюю запись.
  • Ограничьте запрос числом записей, которые мы хотели бы рекомендовать.

Эти шаги преобразуются в сложный запрос, который мы собираемся включить в post_detail view. Откройте файл views.py приложения блога и добавьте следующий импорт в верхней части документа:

from django.db.models import Count

Это агрегатная функция Count в Django ORM. Эта функция позволит нам получать агрегированные показатели. Затем добавьте следующие строки в post_detail view перед функцией render():

# List of similar posts
post_tags_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tags_ids).exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:4]

Давайте разберем этот код:

  1. Мы извлекаем список идентификаторов(id) тегов текущей записи. Набор запросов values_list() возвращает кортежи со значениями для заданных полей. Мы передаем в него flat=True, чтобы получить список, например [1, 2, 3,...].
  2. Мы получим все записи, которые содержат любые из этих тегов, исключая текущую запись.
  3. Для создания вычисляемого same_tags, содержащего число тегов, общих со всеми запрошенными тегами, используется статистическая функция Count.
  4. Мы возвращаем результат по количеству общих тегов и публикации для отображения последних записей, сначала для записей с одинаковым числом общих тегов. Мы срезали результат, чтобы получить только первые четыре записи.

Добавьте объект similar_posts в контекстный словарь для функции render() следующим образом:

return render(request,
              'blog/post/detail.html',
              {'post': post,
              'comments': comments,
              'comment_form': comment_form,
              'similar_posts': similar_posts})

Теперь отредактируйте шаблон blog/post/detail.html и добавьте следующий код перед списком комментариев:

<h2>Similar posts</h2>
{% for post in similar_posts %}
    <p>
        <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
    </p>
{% empty %}
    There are no similar posts yet.
{% endfor %}

Также рекомендуется добавить список тегов к шаблону post detail таким же образом, как и в шаблоне списка постов. Теперь страница post detail должна выглядеть следующим образом:

Вы успешно рекомендуете схожие записи пользователям. django-taggit также включает в себя similar_objects() manager, который можно использовать для извлечения объектов с помощью общих тегов. О django-taggit вы можете узнать больше здесь http://django-taggit.readthedocs.org/en/latest/api.html

results matching ""

    No results matching ""