среда, 28 декабря 2011 г.

Django: "Кто на сайте" ?


В одном из проектов понадобилось реализовать функцию "Кто на сайте". Средней продолжительности копания привели к модулю django-onlineiser.


$sudo easy install django-onlineuser


далее в settings.py:

#добавляем приложение в список используемых в проекте
INSTALLED_APPS += ('oblineuser')

#регистрируем его middleware в соответствующем списке
MIDDLEWARE_CLASSES += ('onlineuser.middleware.OnlineUserMiddleware')



в нужном html шаблоне подгружаем теги этого приложения и там же отображаем html-код этой приблуды

{% load onlineuser_tags %}
Кто здесь?
{%onlineinfos%}


У меня, чтобы заработало пришлось немного модифицировать код класса из middleware.py, обернув имеющийся там код в try except

class OnlineUserMiddleware:
    def process_request(self, request):
        try:
            user = request.user
            ip=request.META['REMOTE_ADDR']
            if user.is_authenticated():
                o, created = Online.objects.get_or_create(user=user)
                o.session_key = ip
            else:
                o, created = Online.objects.get_or_create(ident=ip)
                o.session_key = ip
            if not created:
                o.save()
        except:
            return


В результате видим простейшую статистику о гостях и онлайн юзерах.

С первого взгляда все ок и автору приложения в любом случае спасибо.

Но чуть позже стало понятно 2 факта (помимо бага описанного выше):
1. сразу после логаута пользователя счетчик пользователей не уменьшается, а счетик гостей не увеличивается
2. после логина счетчик гостей не уменьшается, хотя счетчик пользователей увеличивается

Не совсем релевантно получается.

Я допилил это приложение с помощью сигналов о логине и логауте:


#этот код я добавил в middleware.py рассматриваемого приложения, хотя можно и любое другое удобное место 
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver
@receiver(user_logged_in)
def count_logins(sender,request,user,**kwargs):
    ip=request.META['REMOTE_ADDR']
    g=Online.objects.get(session_key=ip, user=None)
    if(g):
        g.delete() #удаляем гостя , после того , как он стал залогиненным юзером
    #создаем или обновляем запись в таблице приложения (этот код я скопипастил из имеющегося миддлваре-класса
    o, created = Online.objects.get_or_create(user=user) 
    o.session_key = ip
    if not created:
        o.save()    
 
@receiver(user_logged_out)
def count_logouts(sender,request,user,**kwargs):
    o=Online.objects.get(user=user) 
    o.delete() #сразу при логауте удаляем запись из таблицы



Если в ближайшее время не придумаю как более красиво это все дело улучшить, отпишу автору или посто форкну это приложение )

четверг, 1 декабря 2011 г.

Django: Добавляем свои собственные проверки объектов в админку



Если понадобилось дополнить стандарные проверки, которые делает Django при создании, редактировании, удалении объектов через панель администратора, то существует несколько извращенных способов.
Опишу самый простой, наглядный и незатратный.

Начиная с версии 1.2 в Django позволяет добавлять в модель метод clean, в котором и предлагается реализовывать логику нужных вам проверок.

Например у вас есть таблица "Матч" , в полях которой есть две ссылки (ForeignKey) на таблицу "Команда". То есть играют две команды ) Сама с собой команда, понятно, играть не может. По крайней мере в тех командных видах спорта , о которых доводилось слышать )

Код проверки будет примерно прост (добавить метод в класс модели "Матч"):


    def clean(self):
        from django.core.exceptions import ValidationError
        if(self.team1.id == self.team2.id):
            raise ValidationError('Команда не может играть сама c собой.')            

В результате , при попытке сохранения матча где команда намеревается рубиться сама с собой , админ увидит красненький баннер с соответствующим сообщением.

p.s. сейчас в голову пришла мыслишка: будет ли вызываться этот метод, при сохранении объекта не через админку..хм.. надо будет матчасть почитать или выяснить эмпирически.

Если кто уже в курсе - буду признателен за ответ. Хотя кому это я, читателей пока у меня судя по всему нет )))))