Evgenij LegotskojNov. 13, 2016, 1:04 a.m.

Django - Tutorial 014. Displays a list of popular articles on Django

Many blogs and news sites to keep the audience's attention using such methods as ranking popular articles this week, related publications, and some major resources and more advice on user preferences.

First, it was decided to do - it displays a list of popular articles. The first version of the popular articles was based on a general counter views and eventually deduced the article with the most views. This is generally a bad option, since the TOP will result in articles just scored the highest number of views for all time.

Therefore it was necessary to change something. As a result, the output has been introduced popular articles in last 7 days in its simplest form. That is, the table has been added which introduced views of articles by day. Of course, the accuracy of counting under heavy load can vary greatly, but attendance is not reached the 5,000 - 10,000 unique visitors a day - it's not so important.

Now lets proceed with an example of how to make a list of popular articles Django .

Article and Statistics models

Here is a stripped-down version of the model for items, as in this case, I'm interested in only the title of the article.

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

    title = models.CharField('Title', max_length=200)

    def __str__(self):
        return self.title

A statistical model views on articles will be the next code.

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

    article = models.ForeignKey(Article)                    
    date = models.DateField('Date', default=timezone.now)   
    views = models.IntegerField('Views', default=0)     

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

class ArticleStatisticAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'date', 'views')  
    search_fields = ('__str__', )                

In this code, made two models:

  1. The model itself to collect statistics
    Model to display the data in the admin area.

These models will be written in models.py file.

Do not forget to also register the model in the admin in admin.py file.

from django.contrib import admin

from .models import Article, ArticleStatistic, ArticleStatisticAdmin

admin.site.register(ArticleStatistic, ArticleStatisticAdmin)

Then do not forget to do a database migration.

python manage.db makemigrations
python manage.db migrate


Once we have added to the model, it remains to add the conclusion of popular articles and make the counting statistics when requested article from the server.

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

# To work with the models of articles I have used knowledge module
from knowledge.models import Article, ArticleStatistic  

# while module is used for displaying articles post
# This was done in order to URL items was the following form
#    /post/42/ - where 42 - it is id od article in database
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 = {}

        # Then we pick up the object of today's statistics, or create a new one if required
        obj, created = ArticleStatistic.objects.get_or_create(
                "article": article,
                "date": timezone.now()
            # At the same time define a fence or statistics object creation
            # by two fields: date and a foreign key to the article
            date=timezone.now(), article=article    
        obj.views += 1    

        # Now pick up the list of the last 5 most popular articles of the week
        popular = ArticleStatistic.objects.filter(
            # filter records in the last 7 days
            date__range=[timezone.now() - timezone.timedelta(7), timezone.now()]
            # Taking the field of interest to us, namely, the id and the title
            # Unfortunately we can not to pick up an object on the foreign key in this case 
            # Only the specific field of the object
            'article_id', 'article__title'
            # Summing over rated recording
            # All sum properly with matching fields for the requested objects
            # sort the records Descending
            '-views')[:5]  # Take 5 last records

        context['popular_list'] = popular # We went to the context of the list of articles

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

Display template

And now just be displayed in page template list of popular articles of the week. I'll note that only give you a template to display a list. This is enough to understand how to get a list of articles on the page.

Do not also forget that I am using django_bootstrap3, therefore, the pattern looks accordingly.

{% 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>
{% endfor %}
{% endif %}

URL pattern:

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


The list of popular articles will be similar to that used on this site, but without the total number of views and, in the admin stats will look like this:

For Django I recommend VDS-server of Timeweb hoster .

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate
  • #
  • Jan. 5, 2017, 2:20 a.m.

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

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


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

Здравствуйте Евгений! Чему может быть причиной эта ошибка:
Reverse for 'post' with arguments '(1,)' not found. 1 pattern(s) tried: ['main\\/(?P<section>[^/]+)\\/(?P<post_id>[^/]+)\\/$']
Мой урл, и вьюха.
app_name = 'main'

urlpatterns = [
    path('', views.Index, name='index'),
    path('<section>/', views.SectionView.as_view(), name='section'),
    path('<section>/<post_id>/', views.PostView.as_view(), name='post')

class PostView(View):
    template_name = 'main/post.html'    # Шаблон статьи
    def get(self, request, *args, **kwargs):
        post = get_object_or_404(Post, id=self.kwargs['post_id'])
        context = {}
        obj, created = PostStatistic.objects.get_or_create(defaults={"post": post,"date": timezone.now()}, date=timezone.now(), post=post)
        obj.views += 1
        popular = PostStatistic.objects.filter(
            date__range=[timezone.now() - timezone.timedelta(7), timezone.now()]
            'post_id', 'post__title'

        context['post_id'] = post
        context['popular_list'] = popular
        context['username'] = auth.get_user(request).username
        return render_to_response(template_name=self.template_name, context=context)
Ну и шаблон до кучи:

{% if popular_list %}
<ul class="list-group">
<li class="list-group-item active"><strong>Популярные публикации за неделю</strong></li>
{% for pop_post in popular_list %}
    <li class="list-group-item">
    <a href="{% url 'main:post' pop_post.post_id %}">{{ pop_post.post__title }}</a>
{% endfor %}
{% endif %}
Очень надеюсь на вашу помощь.

Добрый день!

Во-первых перепишите urlpatterns так

urlpatterns = [
    path('', views.Index, name='index'),
    path('<section>/<post_id>/', views.PostView.as_view(), name='post'),
    path('<section>/', views.SectionView.as_view(), name='section')
Маршрутизатор url в Django иногда тупит из-за последовательности объявления шаблонов. Поэтому лучше шаблоны url прописывать в алфавитном порядке и больший шаблон ставить первым.

Во-вторых вы используете id, а там нужно тогда указать, что это у вас целочисленное значение, по умолчанию обрабатывается как строка. Значит результирующая запись будет такой.
urlpatterns = [
    path('', views.Index, name='index'),
    path('<section>/<int:post_id>/', views.PostView.as_view(), name='post'),
    path('<section>/', views.SectionView.as_view(), name='section')

К сожалению это не изменило ситуацию. Убираю ссылку на статью из шаблона и все работает.  Вероятно не правильно сформирована ссылка в шаблоне.

Да. действительно, на это я не обратил внимания. Напишите либо так

<a href="{% url 'main:post' pop_post.id %}">{{ pop_post.post__title }}</a>
либо так
<a href="{% url 'main:post' pop_post.pk %}">{{ pop_post.post__title }}</a>

И этот вариант к сожалению не рабочий =(

Извиняюсь, неправильно написал последний ответ. В рамках данной статьи это не правильно, у вас же во вьюшке формируется объект у которого в post_id должен содержаться его PrimaryKey.

Вообще можете показать модель PostStatistic? Я явно что-то упускаю здесь.

Такая же как и у вас вроди бы.

class PostStatistic(models.Model):
    class Meta:
        db_table = "PostStatistic"
    post = models.ForeignKey(Post, on_delete=models.CASCADE) 
    date = models.DateField('Дата', default=timezone.now)   
    views = models.IntegerField('Просмотры', default=0)
    def __str__(self):
        return self.post.title

мда... глупо как-то получилось. У вас же в шаблоне два аргумента задано.

Один аргумент - это либо id раздела, либо его имя (вомзожно тоже самое slug поле, а вторым параметром идёт id самого поста).

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

Что-то типо такого
<a href="{% url 'main:post' pop_post.post__section pop_post.post_id %}">{{ pop_post.post__title }}</a>

Думаю, что вам нужно немного поправить ещё вот этот метод
popular = PostStatistic.objects.filter(
    date__range=[timezone.now() - timezone.timedelta(7), timezone.now()]
    'post_id', 'post__title', 'post__section'

Если делать таким образом, то вьюха отдает id категории а не slug. Попробую пост сделать отдельным приложением. Во всяком случае большое спасибо за помощь.

А. Так вы slug использовали? Тогда там надо брать поле slug из section в запросе.

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

Вот и я пришел к тому же пути. Так вроди бы логично и красиво выглядит.

Я как понял, этот метод создает статистику каждый день (на каждый день), не удаляя старые данные за день и выводит все данные за сегодняшние просмотры у всех статей?


Only authorized users can post comments.
Please, Log in or Sign up

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting

C++ - Test 001. The first program and data types

  • Result:80points,
  • Rating points4

C++ - Test 001. The first program and data types

  • Result:46points,
  • Rating points-6

Qt - Test 001. Signals and slots

  • Result:94points,
  • Rating points8
Last comments

Как соответствовать новым требованиям Google Play

Ку всем! Вопрос! Как с помощью JNI вызвать оплату на android устройстве? Попробовал Qt Purchasing вроде пошло... но android пишет что библиотека устарела. В qt6 пока поддержки purchasing нет. Р…

Django - Tutorial 014. Displays a list of popular articles on Django

Я как понял, этот метод создает статистику каждый день (на каждый день), не удаляя старые данные за день и выводит все данные за сегодняшние просмотры у всех статей?

Qt/C++ - Lesson 006. QSqlQueryModel – Tables in Qt with SQL-query

Изменить запрос при создании модели.
  • Livis
  • May 30, 2021, 1:18 p.m.

Django - Tutorial 001. Deploying a site on Django + PostgreSQL + Gunicorn + Nginx

Отвечал на все команды после sudo service supervisor start Исправил таким образом sudo killall supervisordsudo supervisord -c /etc/supervisor/supervisord.conf

Django - Tutorial 001. Deploying a site on Django + PostgreSQL + Gunicorn + Nginx

Это на какую команду так отвечает?
Now discuss on the forum
  • vika
  • June 17, 2021, 12:19 a.m.

Вопрос новичка ui-форма

все получилось. создала обьект, исправила ошибки и все заработало. спасибо, что есть с кем поговорить.

Ключевое слово class

Разобрался,на стаковерфлоу нашел топик и понял почему так происходило .

Django как воспользоваться результатом метода?

Priv = 2020 Now = 2021 Next = 2022 Rok = ( (None, "Nie wybran"), (Priv, '2020'), (Now, '2021'), (Next, '2022') ) Rok = models.IntegerField(choices=Rok, de…

QScrollArea dynamically add QCheckBoxes

Всё правильно. Это просто спамер, который отправился в вечный бан.

Папка с шаблоном сайта

Есть проект с поддержкой динамического создания поддоменов. Как назначить разные пути к шаблонам в templates from django.shortcuts import renderfrom horticulture.utilities import get_horticu…
© EVILEG 2015-2021
Recommend hosting TIMEWEB