Skip to content

Instantly share code, notes, and snippets.

@codeboy
Last active August 30, 2015 14:41
Show Gist options
  • Save codeboy/9aaa39f2a0155231cf8a to your computer and use it in GitHub Desktop.
Save codeboy/9aaa39f2a0155231cf8a to your computer and use it in GitHub Desktop.
django middleware for counting visitors
<div class="hidden-xs hidden-sm panel panel-default">
<div class="panel-heading">
<h5 align="center">Сейчас на сайте</h5>
</div>
<div class="list-group">
<li class="list-group-item">пользователей: {{ users_count|add:u_count }} ({{ users_count }})</li>
<li class="list-group-item">гостей: {{ anons_count|add:a_count }} ({{ anons_count }})</li>
</div>
</div>
# -*- coding: utf-8 -*-
import datetime
import random
from django.conf import settings
from django.core.cache import cache
from importlib import import_module
from django.utils.timezone import is_aware, utc
# todo: надо переработать race conditions
class VisitorsCounter(object):
"""
Переменные в кэше:
users_count - количество зарегистрированных пользователей
users_list - словарик с активными пользователями
{'pid' : 'time',}
users_last_update
"""
def process_request(self, request):
delta_time = (datetime.datetime.now() + datetime.timedelta(seconds=settings.VISITORS_MUTE_TIME))
# определяем тип пользователя
if request.user.is_authenticated(): user_type = 'user'
else: user_type = 'anon'
split_path = request.path.split('/') # делим путь
# производим расчёты, только если запрашивалась страница
if split_path[1] == 'media': return # отсеиваем медиа запросы
elif split_path[1] == 'static': return # аналогично отсеиваем статику
else:
if not request.session.session_key: # если у посетителя нет сессии - создадим
request.session.create()
if not request.session.get('last_active'): # если у сессии нет ключа - добавим
request.session['last_active'] = u'%s' % delta_time
self.update_cache(user_type=user_type,
user_id=request.session.session_key,
user_time=delta_time)
else:
active_date = datetime.datetime.strptime(request.session.get('last_active'), "%Y-%m-%d %H:%M:%S.%f")
now = datetime.datetime.now(utc if is_aware(active_date) else None)
if active_date < now:
# print 'session key -', request.session.session_key
self.update_cache(user_type=user_type,
user_id=request.session.session_key,
user_time=delta_time)
request.session['last_active'] = u'%s' % delta_time
cache.set('is_update', 'Yesss!')
else:
cache.set('is_update', 'Nope!')
return
def visitors_iterate(self, visitors_dict, visitor_id=False, visitor_time=False):
"""
перебираем словарь пользователями и датами и создаём новый с теми кто прошел валидацию
"""
now = datetime.datetime.now()
v_count = 0
new_dict = dict()
is_visitor_exist = False # флаг для проверки на добавление нового пользователя
for key, value in visitors_dict.iteritems():
# print key, value
if value >= now:
# print('visitor time ok')
if visitor_id and key == visitor_id:
new_dict[key] = visitor_time
is_visitor_exist = True
else:
new_dict[key] = value
v_count+=1
if visitor_id and not is_visitor_exist: # добавляем нового посетителя
new_dict[visitor_id] = visitor_time
v_count+=1
return new_dict, v_count
def update_cache(self, user_type=False, user_id=False, user_time=False):
"""
"""
# cache.clear()
delta_time = (datetime.datetime.now() + datetime.timedelta(seconds=settings.VISITORS_CASHE_LIVE_TIME))
if user_time:
cache.set('visitors_last_update', user_time)
else:
cache.set('visitors_last_update', delta_time)
# ---------- users ------------#
if not cache.get('users_list'):
if user_type == 'user':
cache.set('users_list', {user_id:user_time}, 60*60)
cache.set('users_count', 1)
# перепроверим анонимов
anon_dict, anon_count = self.visitors_iterate(cache.get('anons_list'))
cache.set('anons_list', anon_dict, 60*60)
cache.set('anons_count', anon_count)
else:
if user_type == 'user':
users_dict, users_count = self.visitors_iterate(cache.get('users_list'), user_id, user_time)
cache.set('users_list', users_dict, 60*60)
cache.set('users_count', users_count)
# перепроверим анонимов
anon_dict, anon_count = self.visitors_iterate(cache.get('anons_list'))
cache.set('anons_list', anon_dict, 60*60)
cache.set('anons_count', anon_count)
# ---------- anons ------------#
if not cache.get('anons_list'):
if user_type == 'anon':
cache.set('anons_list', {user_id:user_time}, 60*60)
cache.set('anons_count', 1)
# перепроверим юзеров
users_dict, users_count = self.visitors_iterate(cache.get('users_list'))
cache.set('users_list', users_dict, 60*60)
cache.set('users_count', users_count)
else:
if user_type == 'anon':
anon_dict, anon_count = self.visitors_iterate(cache.get('anons_list'), user_id, user_time)
cache.set('anons_list', anon_dict, 60*60)
cache.set('anons_count', anon_count)
# перепроверим юзеров
users_dict, users_count = self.visitors_iterate(cache.get('users_list'))
cache.set('users_list', users_dict, 60*60)
cache.set('users_count', users_count)
def get_client_ip(self, request):
""" определяем IP пользователя """
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
# -*- coding: utf-8 -*-
import datetime
import json
import random
from django.utils.timezone import is_aware, utc
from django import template
from django.conf import settings
from django.core.cache import cache
register = template.Library()
@register.inclusion_tag('includes/inc_visitors2.html', takes_context=True)
def visitors_tag(context, polls=False):
""" тег для вывода опросов """
request = context.request
users_count = cache.get('users_count')
users_list = cache.get('users_list')
anons_count = cache.get('anons_count')
anons_list = cache.get('anons_list')
is_update = cache.get('is_update')
# cache.delete('is_update')
count = settings.VISITORS_RANDOM_COUNTER
u_count = random.randint(count[0], count[1])
a_count = random.randint(count[0], count[1])
return {
'users_count': users_count,
'users_list': users_list,
'anons_count': anons_count,
'anons_list': anons_list,
'is_update': is_update,
'u_count': u_count,
'a_count': a_count,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment