Отслеживать количество «просмотров страниц» или «попаданий» объекта? - PullRequest
34 голосов
/ 22 октября 2009

Я уверен, что у кого-то есть подключаемое приложение (или учебное пособие), которое приближается к этому, но у меня возникают проблемы с его поиском: я хочу иметь возможность отслеживать количество «просмотров», которые имеет конкретный объект (как здесь вопрос по stackoverflow имеет «количество просмотров»).

Если пользователь не вошел в систему, я не возражал бы попытаться поместить cookie (или зарегистрировать IP), чтобы они не могли непреднамеренно увеличить количество просмотров путем обновления страницы; и если пользователь вошел в систему, разрешите ему только один «просмотр» между сеансами / браузерами / IP-адресами. Я не думаю, что мне это нужно больше, чем это.

Я полагаю, что лучший способ сделать это - использовать Middleware, который отделен от различных моделей, которые я хочу отслеживать, и использовать выражение F (своего рода) - другие вопросы по stackoverlow ссылались на это ( 1 ) ( 2 ) ( 3 ).

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

Вы видели это?

Ответы [ 6 ]

45 голосов
/ 26 октября 2009

Я не уверен, что мне лучше ответить на мой собственный вопрос, но после небольшой работы я собрал приложение, которое решает проблемы всерьез: django-hitcount .

Вы можете прочитать о том, как его использовать, на странице документации .

Идеи для django-hitcount пришли из обоих моих двух оригинальных ответов ( Teebes -and- vikingosegundo ), которые действительно заставили меня задуматься обо всем этом.

Это моя первая попытка поделиться подключаемым приложением с сообществом, и надеюсь, что кто-то еще найдет его полезным. Спасибо!

22 голосов
/ 22 октября 2009

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

в 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-ссылку, чтобы поисковые системы не увеличивали количество ваших запросов.

Надеюсь, это поможет!

9 голосов
/ 22 октября 2009

Вы можете создать общую модель 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,
        })

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

Поскольку таблица попаданий может быстро расти, вам следует подумать о стратегии удаления.

2 голосов
/ 20 июля 2018

Я знаю, что этот вопрос старый, а также thornomad поставил приложение, чтобы решить проблему и вдохновить меня решением. Я хотел бы поделиться этим решением, так как я не нашел много информации по этой теме, и это может помочь кому-то еще. Мой подход заключается в том, чтобы сделать универсальную модель пригодной для любого представления на основе пути представления (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
1 голос
/ 08 мая 2016

Я сделал это, используя куки. Не знаю, стоит ли это делать или нет. Следующий код сначала ищет уже установленный 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
0 голосов
/ 31 июля 2017

Я сделал это, создав модель PageViews и сделав в ней столбец «Хиты». Каждый раз, когда URL домашней страницы ударил. Я увеличиваю первый и единственный ряд столбца Hit и отображаю его в шаблон. Вот как это выглядит.

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