13 ноября 2013 г.

django: contrib.comments работаем через ajax

Тут рассказ о том, как заставить стандартный django.contrib.comments работать через ajax. Цель была такова: минимальные изменения в клиентских view, чтобы работали стандартные templates перегружаемые, полноценная админка (обычная от приложения comments), да и вообще максимальное использование оригинального кода. Короче, в итоге после нескольких самопроизвольных переписываний (вместе с использованием подобного решения в проектах) получилась минимальная обёртка, которую по идее тоже можно вынести в отдельный app.

Да, скоро это уже не совсем актуально станет (django.contrib.comments устаревший и с версии 1.6 вынесен в отдельный проект), но решение отточилось на третьей версии и мне жалко его терять просто :) Пример тут для версии 1.5.

2 ноября 2013 г.

django: текущий пользователь в логах

Удобно в логах иметь текущего залогиненого юзера, чтобы видно было на ком падает, удобнее разбираться. Для логгера "django.request" передаётся экстра-параметр request. Его можно вытащить и залоггировать. Например, с помощью кастомного фильтра. Фильтр добавляет в вывод форматтера поле "user" с именем (строковое представление#id) юзера если оно есть. Фильтр вешается на нужные handlers. А в соответствующие formatters на этих handlers добавляется поле "user". В фильтре проверка на существование атрибутов request и request.user обязательна, если текущий formatter повешен на что-либо, кроме логгера "django.request", иначе будет падать в попытке найти поле с ид "user".

class RequestPushUserFilter(logging.Filter):
    def filter(self, record):
        if hasattr(record, 'request'):
            if hasattr(record.request, 'user'):
                record.user = u'%s#%s' % (record.request.user, record.request.user.pk)
            else:
                record.user = '?'
        else:
            record.user = '-'
        return True


LOGGING = {
    ...
    'filters': {
        ...
        'request_pushuser_filter': {
            '()': 'project.settings.RequestPushUserFilter',
        },
    },
    ...
    'formatters': {
        'standard': {
            'format': "[%(asctime)s] %(levelname)s [%(name)s:%(module)s:%(lineno)s] [%(user)s] %(message)s",
            'datefmt': '%d.%m.%Y %H:%M:%S',
        },
    },
    ...
    'handlers': {
        'logfile': {
            ...
            'filters': ['request_pushuser_filter'],
            ...
            'formatter': 'standard',
        },
    ...
В итоге в логах будет примерно так:
[31.10.2013 00:43:20] ERROR [django.request:base:212] [Driver John#1] Internal Server Error: блабла

См. также про логгирование в файл django.