Реклама

Django - Урок 014. Вывод списка популярных статей на Django

РуководствоDjangoDjango, популярные статьи, статистика2593

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

Первое, что было решено сделать - это вывод списка популярных статей. Первый вариант популярных статей был основан на общем счётчике просмотров и в итоге выводил статьи с самым большим количество просмотров. Это в целом плохой вариант, поскольку в ТОПе в итоге окажутся статьи просто набравшие самое большое количество просмотров за всё время.

Следовательно нужно было что-то менять. В результате был внедрен вывод популярных статей за последние 7 дней в самом простом варианте. То есть, добавлена была таблица в которую вносится количество просмотров статей по дням. Конечно, точность подсчётов при большой нагрузке может очень сильно варьироваться, но пока посещаемость не достигла 5000 - 10000 уникальных посетителей в сутки - это не настолько важно.

А теперь давайте разберём пример того, как сделать такой список популярных статей средствами Django .

Модели статей и статистики

Приведу урезанный вариант модели для статей, поскольку в данном случае меня интересует только заголовок статьи.

class Article(models.Model):
    class Meta:
        db_table = "article"

    title = models.CharField('Название статьи', max_length=200)

    def __str__(self):
        return self.title

А для модели статистики просмотров по статьям код будет следующий.

class ArticleStatistic(models.Model):
    class Meta:
        db_table = "ArticleStatistic"

    article = models.ForeignKey(Article)                    # внешний ключ на статью
    date = models.DateField('Дата', default=timezone.now)   # дата
    views = models.IntegerField('Просмотры', default=0)     # количество просмотров в эту дату

    def __str__(self):
        return self.article.title


class ArticleStatisticAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'date', 'views')  # отображаемые поля в админке
    search_fields = ('__str__', )                # поле, по которому производится поиск

В данном коде сделано две модели:

  1. Сама модель для сбора статистики
  2. Модель для отображения данных в админке.

Эти модели будут написаны в файле models.py.

Не забываем также зарегистрировать эти модели в админке в файле admin.py.

from django.contrib import admin

from .models import Article, ArticleStatistic, ArticleStatisticAdmin

admin.site.register(Article)
admin.site.register(ArticleStatistic, ArticleStatisticAdmin)

После чего не забываем сделать миграцию базы данных.

python manage.db makemigrations
python manage.db migrate

Представление для отображения страницы

После того, как у нас добавлены модели, осталось добавить вывод популярных статей и сделать подсчёт статистики при запросе статьи с сервера.

from django.views import View
from django.shortcuts import render_to_response, get_object_or_404
from django.utils import timezone
from django.db.models import Sum

# Для работы с моделями статей у меня используется модуль knowledge
from knowledge.models import Article, ArticleStatistic  


# тогда как для отображения статей используется модуль post
# Это было сделано для того, чтобы URL статей был следующего вида
#    /post/42/ - где 42 - это id статьи в базе данных
class EArticleView(View):
    template_name = 'knowledge/article.html'    # Шаблон статьи

    def get(self, request, *args, **kwargs):
        article = get_object_or_404(Article, id=self.kwargs['article_id'])    # Забираем статью из базы данных
        context = {}

        # Далее забираем объект сегодняшней статистики или создаём новый, если требуется
        obj, created = ArticleStatistic.objects.get_or_create(
            defaults={
                "article": article,
                "date": timezone.now()
            },
            # При этом определяем, забор объекта статистики или его создание
            # по двум полям: дата и внешний ключ на статью
            date=timezone.now(), article=article    
        )
        obj.views += 1    # инкрементируем счётчик просмотров и обновляем поле в базе данных
        obj.save(update_fields=['views'])

        # А теперь забираем список 5 последний самых популярных статей за неделю
        popular = ArticleStatistic.objects.filter(
            # отфильтровываем записи за последние 7 дней
            date__range=[timezone.now() - timezone.timedelta(7), timezone.now()]
        ).values(
            # Забираем интересующие нас поля, а именно id и заголовок
            # К сожалению забрать объект по внешнему ключу в данном случае не получится
            # Только конкретные поля из объекта
            'article_id', 'article__title'
        ).annotate(
            # Суммируем записи по просмотрам
            # Всё суммируется корректно с соответствием по запрашиваемым полям объектов 
            views=Sum('views')
        ).order_by(
            # отсортируем записи по убыванию
            '-views')[:5]  # Заберём последние пять записей

        context['popular_list'] = popular # Отправим в контекст список статей

        return render_to_response(template_name=self.template_name, context=context)

Отображение в шаблоне

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

Не забываем также что я использую django_bootstrap3 , поэтому шаблон выглядит соответствующим образом.

{% if popular_list %}{% load bootstrap3 %}
<ul class="list-group">
<li class="list-group-item active"><strong>Популярные публикации за неделю</strong></li>
{% for pop_article in popular_list %}
    <li class="list-group-item">
    <a href="{% url 'post:article' pop_article.article_id %}">{{ pop_article.article__title }}</a>
    </li>
{% endfor %}
</ul>
{% endif %}

Чтобы не было недомолвок, приведу шаблон url для запроса страниц с сайта:

url(r'^(?P<article_id>[0-9]+)/$', views.EArticleView.as_view(), name='article'),

Итог

Список популярных статей будет похож на тот, что используется на данном сайте, только без общего количества просмотров, а в админке статистика будет выглядеть следующим образом:

Реклама

Комментарии

  • #
  • 5 января 2017 г. 13:20

Добрый день! В Django я новичок. По Вашей инструкции у меня получилось вывести популярные статьи, но они видны только в статье. Как вывести их на главную страницу? Заранее спасибо за ответ!

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

Спасибо Вам большое!!!

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
Последние комментарии
  • EVILEG
  • 13 июля 2017 г. 2:12

Qt/C++ - Урок 023. Перетаскивание QGraphicsItem на QGraphicsScene мышью

Ну например так можете сделать.void MoveItem::mousePressEvent(QGraphicsSceneMouseEvent *event){ if (QApplication::mouseButtons() == Qt::RightButton) { this->deleteLa...

  • Mark
  • 13 июля 2017 г. 1:26

Qt/C++ - Урок 023. Перетаскивание QGraphicsItem на QGraphicsScene мышью

Подскажите пожалуйста как в данном проекте по перетаскиванию организовать удаление объекта со scene методом delete item, допустим при щелчке ПКМ по объекту QGraphicsScene. Мои попытки оказалис...

  • EVILEG
  • 10 июля 2017 г. 21:34

Qt/C++ - Урок 048. QThread - работа с потоками с помощью moveToThread

А что делали? Повторяете урок или как? Пытались просто скачать проект в конце статьи и запустить?

Qt/C++ - Урок 048. QThread - работа с потоками с помощью moveToThread

У меня происходит переполнение счетчика count, появляется ошибка malloc(): memory corruption (fast). Не подскажите, как с этим бороться?

  • EVILEG
  • 9 июля 2017 г. 2:07

GameDev на Qt - Урок 3. Уничтожение противников

Поэтому в пятом уроке есть исходники всего проекта )))). Вообще, все эти материалы были не предыдущей версии сайта, которая на WordPress. Во время переноса мог что-то потерять.

Сейчас обсуждают на форуме

тестирование классов в QT

это вопрос.

Как реализовать отправку e-mail

Возможно что уже и нет необходимости в почтовом клиенте, но в своё время так же столкнулся с данной проблемой в QT. Нашел один интересный проект под названием libqxt, там реализовано дов...

  • Asteri
  • 14 июля 2017 г. 12:23

css

Делюсь, может, пригодится когда-нибудь) QTableView QHeaderView { background-color: #ffffff; } Вот так эта проблема лечится, градиент задать не получается, но хоть...

  • EVILEG
  • 12 июля 2017 г. 19:52

QSqlQuery выполнение sql запросов из файла

Мне думается, что это уже будет дело вкуса и вашего взгляда на проект. Если Вы действительно собираетесь просто скармливать своему софту SQL скрипты, которые должны будут выполняться для...

QML Canvas + Line. Bug?

Вот оно что, значит не баг) Спасибо