Acompanhe o número de "visualizações de página" ou "hits" de um objeto?

StackOverflow https://stackoverflow.com/questions/1603340

  •  05-07-2019
  •  | 
  •  

Pergunta

Estou certo de que alguém tem um aplicativo (ou tutorial) flasgável por aí que se aproxima disso, mas tenho problemas para encontrá -lo: quero poder rastrear o número de "visualizações" que um objeto em particular tem (assim como uma pergunta aqui no Stackoverflow tem uma "contagem de visualização").

Se o usuário não estiver conectado, eu não me importaria de tentar colocar um cookie (ou registrar um IP) para que eles não possam acionar inadvertidamente a contagem de visualização, atualizando a página; E se um usuário estiver conectado, permita -lhes apenas uma "visualização" entre sessões/navegadores/endereços IP. Acho que não preciso mais que isso.

Eu acho que a melhor maneira de fazer isso é com o middleware que é dissociado dos vários modelos que quero rastrear e usar uma expressão F (das espécies) - outras perguntas no Stackoverlow aludiram a isso (1) (2) (3).

Mas eu me pergunto se esse código já existe na natureza - porque não sou o codificador mais salvo e tenho certeza de que alguém poderia fazê -lo melhor. Sorriso.

Você viu isso?

Foi útil?

Solução

Não tenho certeza se está do melhor gosto para responder à minha própria pergunta, mas, depois de um pouco de trabalho, montei um aplicativo que resolve os problemas a sério: Django-Hitcount.

Você pode ler sobre como usá -lo em a página de documentação.

As idéias para o django-hitcount vieram de ambas as minhas duas respostas originais (Teebes -e- Vikingosegundo), que realmente me fez começar a pensar sobre a coisa toda.

Esta é a minha primeira tentativa de compartilhar um aplicativo flugable com a comunidade e espero que alguém ache isso útil. Obrigado!

Outras dicas

Você deve usar a estrutura de sessão interna do Django, ele já faz muito disso para você. Eu implementei isso da seguinte maneira com um aplicativo de perguntas e respostas onde eu queria rastrear visualizações:

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

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

O Vikingosegundo provavelmente está certo, embora o uso do tipo conteúdo seja provavelmente a solução mais reutilizável, mas definitivamente não reinvente a roda em termos de sessões de rastreamento, o Django já faz isso!

Última coisa, você provavelmente deve ter a opinião de que os registros que o hit são chamados via Ajax ou um link CSS para que os mecanismos de pesquisa não acelerem suas contagens.

Espero que ajude!

Você pode criar um modelo de sucesso 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')

em sua visão.py você escreve esta função:

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)

e as opiniões que você está interessado em troca

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

Essa abordagem oferece o poder, não apenas para contar o golpe, mas para filtrar a história de sucesso por tempo, contentType e assim por diante ...

Como a tabela de sucesso pode estar crescendo rapidamente, você deve pensar em uma estratégia de exclusão.

Eu sei que essa pergunta é antiga e também Thornomad colocou um aplicativo para resolver o problema e me inspirar para mim. Gostaria de compartilhar essa solução, pois não encontrei muitas informações sobre esse tópico e isso pode ajudar outra pessoa. Minha abordagem é fazer um modelo genérico pode ser usado com qualquer visualização com base no caminho de visualização (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

Eu fiz isso usando cookies. Não sei se é uma boa ideia fazer isso ou não. O código a seguir procura um cookie já definido primeiro, se existir, aumenta o contador total_view se não estiver lá, aumenta o total_views e o UNECLESE_VIELS. Total_Views e ULEM_VIELS são um campo de um modelo 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

Fiz isso criando uma página de modelo de modelo e fazendo uma coluna "hits" nela. Toda vez que o URL da página inicial é atingida. Aumente a primeira e a única linha da coluna e a renderiza no modelo. Aqui está como fica.

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)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top