#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?