¿Seguir el número de “vistas de página” o “visitas” de un objeto?

Estoy seguro de que alguien tiene una aplicación enchufable (o tutorial) que se aproxima a esto, pero tengo problemas para encontrarlo: quiero poder seguir el número de “vistas” que tiene un objeto en particular (al igual que una pregunta aquí) en stackoverflow tiene un “recuento de vista”).

Si el usuario no ha iniciado sesión, no me importaría intentar colocar una cookie (o registrar una dirección de IP) para que no puedan ejecutar inadvertidamente el recuento de vistas actualizando la página; y si un usuario está conectado, solo les permite una “vista” a través de sesiones / navegadores / direcciones IP. No creo que lo necesite más elegante que eso.

Me imagino que la mejor manera de hacer esto es con Middleware que está desacoplado de los diversos modelos que quiero rastrear y usando una expresión F (de tipo) – otras preguntas sobre stackoverlow han aludido a esto ( 1 ) ( 2 ) ( 3 ) .

Pero me pregunto si este código ya existe, porque no soy el codificador más inteligente y estoy seguro de que alguien podría hacerlo mejor. Sonreír.

¿Lo has visto?

No estoy seguro de que sea del mejor gusto responder mi propia pregunta, pero después de un poco de trabajo, armé una aplicación que resuelve los problemas en serio: django-hitcount .

Puede leer sobre cómo usarlo en la página de documentación .

Las ideas para django-hitcount vinieron de mis dos respuestas originales ( Teebes -y- vikingosegundo ), lo que realmente me hizo comenzar a pensar en todo.

Este es mi primer bash de compartir una aplicación conectable con la comunidad y espero que alguien más lo encuentre útil. ¡Gracias!

Debe usar el marco de sesión integrado de django, ya hace mucho de esto por usted. Implementé esto de la siguiente manera con una aplicación de preguntas y respuestas donde quería hacer un seguimiento de las vistas:

en 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()) 

en 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()) 

Probablemente Vikingosegundo tenga razón al decir que usar el tipo de contenido es probablemente la solución más reutilizable, pero definitivamente no reinventar la rueda en términos de seguimiento de sesiones, ¡Django ya lo hace!

Por último, probablemente debería tener la vista que registra el hit sea llamada a través de Ajax o un enlace CSS para que los motores de búsqueda no aceleren sus conteos.

¡Espero que ayude!

Reitero mi idea, que ya escribí como respuesta a una de las preguntas mencionadas, donde no llamó la atención: D

podrías crear un modelo Hit genérico

 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') 

en su view.py usted escribe esta función:

 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) 

y las opiniones que le interesan regresan

 return render_to_response_hit_count(request, 'map/list.html',['list',], { 'list': l, }) 

Este enfoque le da el poder, no solo para contar el golpe, sino para filtrar el historial de aciertos por tiempo, tipo de contenido, etc.

Como la tabla de aciertos puede estar creciendo rápidamente, debes pensar en una estrategia de eliminación.

Código no probado

Sé que esta pregunta es antigua y también Thornomad ha puesto una aplicación para resolver el problema y me inspira una solución. Me gustaría compartir esta solución ya que no encontré mucha información sobre este tema y puede ayudar a otra persona. Mi enfoque es hacer que un modelo genérico se pueda usar con cualquier vista basada en la ruta de vista (url).

models.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) 

views.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 

Lo hice usando cookies. No sé si es una buena idea hacer eso o no. El siguiente código busca una cookie ya establecida primero, si existe, aumenta el contador total_vista, si no está allí, aumenta las vistas total_views y unique_views. Tanto total_views como unique_views son un campo de un modelo de 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 

Lo hice creando un modelo de PageViews y haciendo una columna “Hits” en él. Cada vez que se golpea la url de la Página de inicio. Incremento la primera y única fila de columna Hit y la renderizo en la plantilla. Aquí cómo se ve.

Views.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) 

Models.py

 class PageView(models.Model): hits=models.IntegerField(default=0)