На багатьох блогах і сайтах новин для утримання уваги аудиторії використовуються такі прийоми, як рейтинг популярних за тиждень статей, схожі публікації, а у деяких великих ресурсів ще й рекомендації щодо переваг користувачів.
Перше, що було вирішено зробити, - це висновок списку популярних статей. Перший варіант популярних статей був заснований на загальному лічильнику переглядів і в результаті виводив статті з найбільшою кількістю переглядів. Це загалом поганий варіант, оскільки в ТОПі в результаті виявляться статті, що просто набрали найбільшу кількість переглядів за весь час.
Відтак треба було щось міняти. В результаті було запроваджено виведення популярних статей за останні 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__', ) # поле, по которому производится поиск
У цьому коді зроблено дві моделі:
- Сама модель для збору статистики
- Модель для відображення даних у адмінці.
Ці моделі будуть написані у файлі 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'),
Підсумок
Список популярних статей буде схожий на той, що використовується на даному сайті, тільки без загальної кількості переглядів, а в адмінці статистика виглядатиме так:
Для Django рекомендую VDS-сервера хостера Timeweb .
Добрый день! В Django я новичок. По Вашей инструкции у меня получилось вывести популярные статьи, но они видны только в статье. Как вывести их на главную страницу? Заранее спасибо за ответ!
Я подумал, что этот вопрос можно рассмотреть немного подробнее, поэтому представил в виде отдельной статьи. Можете посмотреть вариант решения здесь: Вывод списка популярных статей на любой странице сайта
Спасибо Вам большое!!!
Добрый день!
Во-первых перепишите urlpatterns так
Во-вторых вы используете id, а там нужно тогда указать, что это у вас целочисленное значение, по умолчанию обрабатывается как строка. Значит результирующая запись будет такой.
К сожалению это не изменило ситуацию. Убираю ссылку на статью из шаблона и все работает. Вероятно не правильно сформирована ссылка в шаблоне.
Да. действительно, на это я не обратил внимания. Напишите либо так
И этот вариант к сожалению не рабочий =(
Извиняюсь, неправильно написал последний ответ. В рамках данной статьи это не правильно, у вас же во вьюшке формируется объект у которого в post_id должен содержаться его PrimaryKey.
Такая же как и у вас вроди бы.
мда... глупо как-то получилось. У вас же в шаблоне два аргумента задано.
Если делать таким образом, то вьюха отдает id категории а не slug. Попробую пост сделать отдельным приложением. Во всяком случае большое спасибо за помощь.
А. Так вы slug использовали? Тогда там надо брать поле slug из section в запросе.
Вот и я пришел к тому же пути. Так вроди бы логично и красиво выглядит.
Я как понял, этот метод создает статистику каждый день (на каждый день), не удаляя старые данные за день и выводит все данные за сегодняшние просмотры у всех статей?
Да, именно такой и была задумка
спасибо