Last active
August 30, 2015 14:41
-
-
Save codeboy/9aaa39f2a0155231cf8a to your computer and use it in GitHub Desktop.
django middleware for counting visitors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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