Как сделать так, чтобы количество посещений было отдельным для каждого элемента

#django #hitcounter #visitor-statistic

Вопрос:

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

     def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['comments'] = Comment.objects.filter(item=self.object)
        context['form'] = CommentCreationForm()
        num_visits = self.request.session.get('num_visits', 0)
        self.request.session['num_visits'] = num_visits   1
        context['visits'] = num_visits
        return context
 

Комментарии:

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

2. Поэтому я должен изменять модели, а не использовать ванильные сеансы и посещения.

3. добавьте поле внутри модели товара и считайте его с каждым щелчком мыши.

4. @MaceiejWojtkowiak: если вы хотите подсчитать общее количество посетителей, да. В противном случае, как только сеанс закончится (например, пользователь перезапустит браузер), обычно для этого пользователя счетчик будет равен нулю, и, кроме того, посещения других пользователей не будут иметь никакого значения

5. Можете ли вы поделиться моделью self.object предмета?

Ответ №1:

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

Если вы хотите отслеживать общее количество посещений на одного пользователя, вам нужно будет сохранить данные о посещениях. Вы можете сделать это с помощью дополнительной модели, которая, например, каждый раз создает новую запись, когда (зарегистрированный) пользователь посещает страницу, или мы можем работать с простым счетчиком. Если мы хотим запретить подсчет одного и того же пользователя несколько раз, если он посещает один и тот же объект несколько раз, имеет больше смысла работать с ManyToManyField пользователем.

Вариант 1: простой IntegerField

Простая реализация, которая просто подсчитывает количество посещений и, таким образом, считает одного и того же пользователя дважды, если этот пользователь посещает объект дважды, может быть реализована с добавлением IntegerField для подсчета количества посещений, это выглядит так. Мы можем написать абстрактную модель для этого:

 class WithVisitCounter(models.Model):
    visits = models.IntegerField(editable=False, default=0)

    class Meta:
        abstract = True 

а затем пусть модель унаследует это:

 class BlogPost(WithVisitCounter, models.Model):
    # ⋮ 

тогда мы сможем приготовить миксин WithVisitCounterMixin :

 from django.views.generic.detail import SingleObjectMixin

class WithVisitCounterMixin(SingleObjectMixin):

    def get_object(self, *args, **kwargs):
        obj = super().get_object(*args, **kwargs)
        old_visit = obj.visits
        obj.visits = F('visits')   1
        obj.save(updated_fields=['visits'])
        obj.visits = old_visit   1
        return obj

    def get_context_data(self, *args, **kwargs):
        cd = super().get_context_data(*args, **kwargs)
        cd['visits'] = self.object.visits
        return cd 

Тогда мы можем использовать это Mixin во всех представлениях, у которых есть SingleObjectMixin как a DetailView , так и UpdateView :

 class BlogPostDetailView(WithVisitCounterMixin, DetailView):
    # ⋮ 

Это передаст количество посетителей в visits контекстные данные, чтобы вы могли отобразить их с {{ visits }} помощью или с {{ object.visits }} помощью , если объект передается в шаблон.

Вариант 2: A ManyToManyField для модели пользователя

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

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

 from django.conf import settings

class WithVisitCounter(models.Model):
    visitors = models.ManyToManyField(
        to=settings.AUTH_USER_MODEL,
        related_name='%(model_name)s_visits'
    )

    class Meta:
        abstract = True

class BlogPost(WithVisitCounter, models.Model):
    # ⋮ 

Затем мы можем определить a WithVisitCounterMixin точно так же, как мы это сделали для первого варианта. В этом случае мы добавим ссылку с объекта на вошедшего пользователя:

 from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.detail import SingleObjectMixin

class WithVisitCounterMixin(SingleObjectMixin):

    def get_object(self, *args, **kwargs):
        obj = super().get_object(*args, **kwargs)
        obj.visitors.add(self.request.user)
        return obj

    def get_context_data(self, *args, **kwargs):
        cd = super().get_context_data(*args, **kwargs)
        cd['visits'] = self.object.visitors.count()
        return cd 

для этого единственного объекта мы можем затем получить посетителей, подсчитав количество записей для .visitors каждого из self.object них .

Таким образом, мы можем также использовать эту смесь в DetailView или UpdateView :

 class BlogPostDetailView(WithVisitCounterMixin, DetailView):
    # ⋮ 

Затем мы можем снова использовать {{ visits }} количество посетителей для этого элемента.

Комментарии:

1. Можем ли мы передать эти функции и для Rest API?