Отслеживать количество «просмотров страниц» или «посещений» объекта?
Вопрос
Я уверен, что у кого-то есть подключаемое приложение (или учебное пособие), которое приблизительно соответствует этому, но у меня возникли проблемы с его поиском:Я хочу иметь возможность отслеживать количество «представлений» конкретного объекта (точно так же, как вопрос здесь, в stackoverflow, имеет «количество просмотров»).
Если пользователь не вошел в систему, я бы не прочь попытаться разместить файл cookie (или зарегистрировать IP-адрес), чтобы он не мог случайно увеличить количество просмотров, обновив страницу;и если пользователь вошел в систему, разрешите ему только одно «просмотр» между сеансами/браузерами/IP-адресами.Я не думаю, что мне нужно что-то более изысканное.
Я полагаю, что лучший способ сделать это - использовать промежуточное программное обеспечение, которое отделено от различных моделей, которые я хочу отслеживать, и использовать выражение F (своего рода) - другие вопросы на stackoverlow намекали на это (1) (2) (3).
Но мне интересно, существует ли этот код уже в природе, потому что я не самый опытный программист и уверен, что кто-то мог бы сделать это лучше.Улыбка.
Вы это видели?
Решение
Я не уверен, что мне лучше ответить на мой вопрос, но после небольшой работы я собрал приложение, которое решает проблемы всерьез: django-hitcount .
О том, как его использовать, можно прочитать на странице документации .
Идеи для django-hitcount пришли из обоих моих двух оригинальных ответов ( Тибес -and- vikingosegundo ), что заставило меня задуматься обо всем этом.
Это моя первая попытка поделиться подключаемым приложением с сообществом, и надеюсь, что кто-то найдет его полезным. Спасибо!
Другие советы
Вы должны использовать встроенную сессионную инфраструктуру django, она уже многое сделает для вас. Я реализовал это следующим образом с приложением Q & A, где я хотел отслеживать просмотры:
в models.py:
class QuestionView(models.Model):
question = models.ForeignKey(Question, related_name='questionviews')
ip = models.CharField(max_length=40)
session = models.CharField(max_length=40)
created = models.DateTimeField(default=datetime.datetime.now())
в views.py:
def record_view(request, question_id):
question = get_object_or_404(Question, pk=question_id)
if not QuestionView.objects.filter(
question=question,
session=request.session.session_key):
view = QuestionView(question=question,
ip=request.META['REMOTE_ADDR'],
created=datetime.datetime.now(),
session=request.session.session_key)
view.save()
return HttpResponse(u"%s" % QuestionView.objects.filter(question=question).count())
Vikingosegundo, вероятно, прав, хотя использование типа контента, вероятно, является более подходящим решением, но определенно не изобретать колесо с точки зрения отслеживания сессий, Django уже делает это!
И последнее, у вас, вероятно, должно быть представление, что записи попадания будут вызываться либо через Ajax, либо через css-ссылку, чтобы поисковые системы не увеличивали количество ваших запросов.
Надеюсь, это поможет!
Вы можете создать общую модель Hit
class Hit(models.Model):
date = models.DateTimeField(auto_now=True)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
в вашем view.py вы пишете эту функцию:
def render_to_response_hit_count(request,template_path,keys,response):
for key in keys:
for i in response[key]:
Hit(content_object=i).save()
return render_to_response(template_path, response)
и мнения, которые вы заинтересованы в возвращении
return render_to_response_hit_count(request, 'map/list.html',['list',],
{
'list': l,
})
Этот подход дает вам возможность не только рассчитывать попадания, но и фильтровать историю обращений по времени, типу содержимого и т. д.
Поскольку таблица совпадений может быстро расти, вам следует подумать о стратегии удаления.
Я знаю, что этот вопрос старый, а также шипастый кочевник поставил приложение, чтобы решить проблему и вдохновить меня на решение.Я хотел бы поделиться этим решением, так как я не нашел много информации по этой теме, и оно может помочь кому-то другому.Мой подход заключается в том, чтобы сделать общую модель, которую можно использовать с любым представлением на основе пути представления (url).
модели.py
class UrlHit(models.Model):
url = models.URLField()
hits = models.PositiveIntegerField(default=0)
def __str__(self):
return str(self.url)
def increase(self):
self.hits += 1
self.save()
class HitCount(models.Model):
url_hit = models.ForeignKey(UrlHit, editable=False, on_delete=models.CASCADE)
ip = models.CharField(max_length=40)
session = models.CharField(max_length=40)
date = models.DateTimeField(auto_now=True)
view.py
def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip
def hit_count(request):
if not request.session.session_key:
request.session.save()
s_key = request.session.session_key
ip = get_client_ip(request)
url, url_created = UrlHit.objects.get_or_create(url=request.path)
if url_created:
track, created = HitCount.objects.get_or_create(url_hit=url, ip=ip, session=s_key)
if created:
url.increase()
request.session[ip] = ip
request.session[request.path] = request.path
else:
if ip and request.path not in request.session:
track, created = HitCount.objects.get_or_create(url_hit=url, ip=ip, session=s_key)
if created:
url.increase()
request.session[ip] = ip
request.session[request.path] = request.path
return url.hits
Я сделал это, используя куки. Не знаю, стоит ли это делать или нет. Следующий код сначала ищет уже установленный файл cookie, если он существует, он увеличивает счетчик total_view, если его нет, то он увеличивает и total_views, и unique_views. И total_views, и unique_views являются полями модели Django.
def view(request):
...
cookie_state = request.COOKIES.get('viewed_post_%s' % post_name_slug)
response = render_to_response('community/post.html',context_instance=RequestContext(request, context_dict))
if cookie_state:
Post.objects.filter(id=post.id).update(total_views=F('total_views') + 1)
else:
Post.objects.filter(id=post.id).update(unique_views=F('unique_views') + 1)
Post.objects.filter(id=post.id).update(total_views=F('total_views') + 1)
response.set_cookie('viewed_post_%s' % post_name_slug , True, max_age=2678400)
return response
Я сделал это, создав модель PageViews и добавив в нее столбец «Хиты».Каждый раз при нажатии URL-адреса домашней страницы.Я увеличиваю первую и единственную строку столбца Hit и отображаю ее в шаблоне.Вот как это выглядит.
Просмотры.py
def Home(request):
if(PageView.objects.count()<=0):
x=PageView.objects.create()
x.save()
else:
x=PageView.objects.all()[0]
x.hits=x.hits+1
x.save()
context={'page':x.hits}
return render(request,'home.html',context=context)
Модели.py
class PageView(models.Model):
hits=models.IntegerField(default=0)