БетаЛаборатория - внеочередной IT-блог

Записки обычного программиста

 
FloatField с запятой в Django Forms - Паллиатив

Давно собирался сделать возможность вводить Float разделенные не точкой, а запятой, да никак руки не доходили. Но, сегодня все-таки пришлось сделать, поскольку для заказчика это оказалось критично. В принципе, данная задача решена в отдельном бранче Django, однако я предпочел сделать более простое, но менее полное и гибкое решение - создал специальный FormField. Все что он делает - это заменяет в полученных от пользователя данных запятую на точку, после чего передает управления оригинальному FloatField.

from django import forms

class FloatFieldWithComma(forms.FloatField):
	def clean(self, value):
		# Проверяем задано ли вообще значение
		if value:
			# Если да - заменяем запятую на точку
			value = value.replace(",",  ".")
		return super(FloatFieldWithComma,  self).clean(value)

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

# Модель
class MyModel(models.Model):
	name = models.CharField(max_length=150)
	price = models.FloatField()

# Форма для модели. В таком виде форма будет требовать
# чтобы разделитель обязательно был точкой.
class MyModelForm(forms.ModelForm):
	class Meta:
		model = MyModel
# А с переопределенным полем price валидными будут и
# точка и запятая
class MyModelForm(forms.ModelForm):
	price = FloatFieldWithComma()
	class Meta:
		model = MyModel

Недостатки этого метода в том, что он, во-первых, не прозрачен для django-admin - чтобы все работало, потребуется переопределять формы всех AdminModel в которых нужен ввод чисел с плавающей точкой. А во-вторых, вывод значения поля будет по прежнему с точкой. На данный момент меня такое решение устраивает, однако я попробую придумать что-то более гибкое.

Храните деньги в сберегательной кассе

Кто кладёт деньги в банк, не должен забывать, что он просто седок, а вожжи в руках у банка. (с) Вильгельм Швебель

Есть у меня возле офиса один замечательный банк, по прозванию Финанскредит. Открыл я там на днях себе счет и соорудил карточку - специально для работы с PayPal, поскольку моя основная карта от Альфа-банка там не верифицируется.

Лирическое отступление. Проблема с картам Альфа-банка, насколько я смог разобраться кроется в совместимости авторизационных методов банка и PayPal. PayPal при попытке авторизовать карту отправляет не все требуемые данные, а именно отсутствует CVV2. Альфа-банк же такую транзакцию не принимает, хотя авторизационную сумму в 1,95USD на счету блокирует на 21 день.

И все вроде с Финанскредитом складывалось неплохо - открыли счет и выдали карту буквально за 30 минут (выдали бы быстрее, но принтер карт заклинило) и к PayPal карта тоже замечательно прицепилась. Негативные впечатления начались когда я решил подключить интернет-банк. Для начала надо было пойти в банкомат и активировать услугу, использую секретный временный код, на что банкомат выдавал временный пароль. Далее, первый раз авторизация на сайте происходит по номеру карты и полученному от банкомата паролику. А вот дальше, система просит указать любой логин и пароль... из 4(!) цифр(!). Вся безопасность строится на том, что набор пароля производится на виртуальной клавиатуре. Что она из себя представляет - это панель содержащая 10 картинок на которых при каждом обновлении страницы цифры от 0 до 9 отображаются в случайном порядке. При клике на картинку в поле для пароля попадает идентификатор "ячейки" в которой расположена картинка. То есть на сервер отправляется не сам пароль, а лишь 4 номера ячеек на которые кликнул пользователь. И все бы ничего, но... Во-первых, сессии для отображения картинок обновляются только при обновлении всей страницы. То есть, если не обновив страницу запросить с сервера картинку для любой ячейки, мы получим ту же картинку. Номер ячейки на сервер передается просто в виде GET переменной. То есть, даже если учесть что картинки не кэшируются, злоумышленник может просто повторно сгрузить все картинки с цифрами. Во-вторых, на каждую цифру приходится всего два(!) варианта изображения. Это значит что для определения цифры, злоумышленнику даже не потребуется OCR - достаточно просто сравнить полученный файл со всеми 20 возможными. Что же в итоге? Достаточно получить возможность внедрить в браузер произвольный код (фактически без разницы какой - JS, Java или Flash) и злоумышленник знает какие цифры находятся в каждой ячейке, он знает и номер ячеек, которые выбрал пользователь и вуаля - он имеет доступ к нашему интернет-банку. Да, он не может совершать там операции более чем на 500 рублей за раз (для больших требуется код, оправляемый на SMS-номер владельца, если он подключил себе эту услугу). Но вот никаких ограничений на количество таких операций нет, так что...

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

Как я уже говорил - в основном эта карта мне нужна для использование с системой PayPal, так что сразу после активации интернет-банка я верифицировал карту и оплатил одну большую покупку. По моим расчетам, после всех конвертаций и комиссий, на счету должно было остаться чуть меньше 1000 рублей - то есть денег было впритык. Но, каково же было мое удивление, когда на следующий день, банкомат известил меня, что у меня задолженность(!) в 2870 рублей. Интересная у банка получалась математика. Первая мысль была о проблемах самого банкомата, вторая - о каких-нибудьт скрытых комиссиях. Чтобы разобраться, я полез в интернет-банк и запросил выписку. В ней по прежнему значилась цифра "-2870 руб.", однако, по сумме всех транзакций (в том числе и конверсионных) получалось именно так, как я рассчитал - должно было быть чуть меньше тысячи.

Пришлось распечатывать выписку и топать в банк. Там стало еще веселее - оказалось, что банковская программа вообще моих расходных транзакций не видит, только пополнения, но при этом я все равно в минусе. Обзвонив всех кого можно, менеджеры так и не смогли разобраться в чем дело, и я плюнул и ушел, предупредив что вернусь завтра. В общем, кончилось все тем, что вечером, а вернее почти ночью, мне вернули на счет все чего там не хватало, но никаких разъяснений так и не дали.

Сколько же людей оказалось вот так обмануто? Специально или случайно происходят такие вещи - это уже вопрос отдельный - в моей ситуации я склоняюсь к тому, что это все-таки какая-то программная ошибка, ибо так неумело не воруют. Тут больше меня интересует, сколько людей таких ошибок не замечает. На самом деле, ведь и я бы мог не заметить, если бы не провел всего одну операцию по карте - через месяц или два, исчезновение 100 евро я бы мог отнести к собственной забывчивости, поскольку много оплачиваю через PayPal, а так же периодически расплачиваюсь картами в магазинах и т.д. А что уж говорить о тех, для кого это вообще не деньги...

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

Новый WYSIWYG

Ну вот, переделал django-приложения для работы с WYSIWYG-редакторами. Первоначальная реализация была достаточно кривая, к тому же давала возможность работать только с FCKEditor 2, который уже достаточно устарел. Кроме того, после некоторых оптимизаций работы nginx, она перестала работать =/ Новое приложение уже более корректно, хотя еще тоже не доделано. На данный момент еще не реализована нормальная работа с https, однако это проблема не только данного приложения, но и всей системы в целом.

От использоваия FCK для себя я отказался в пользу TinyMCE. Но в самом приложении я реализую постепенно поддержку минимум 3-4х различных редакторов, после чего выложу это все в open-source. Увы, пока мне приходится все это делать одному. Сейчас я перешел к более-менее активному поиску помошника по django (нужно по работе), но насколько быстрым и успешным будет этот поиск не знаю. Сначала я очень понадеялся на проект http://djangopeople.net, но увы... Как оказалось большая часть москвичей, да и россиян вообще, именно к джанго отношения не имеют. Не совсем мне понятна их мотивация для регистрации на таком сайте, но судя по всему, просто чтобы дополнительно "засветиться"  везде, где могут обитаться потенциальные заказчики. Грустно...

PS: начинаю морально готовиться к тому, что сотрудников надо будет искать не в нашей стране.

Упрощенная Система Налогообложения

Оттого народ голодает, что слишком велики и тяжелы государственные налоги. Это именно причина бедствий народа.
(c) Лао-цзы

Вот я и добрался до написания статьи относительно налогов. По правде говоря, статья эта коснется только Упрощенной Системы Налогообложения, поскольку с остальными я дела не имел, а заниматься копипастом с юридических сайтов как-то не хочется.
 
Итак, что же такое УСН, или "Упрощенка"? В 2003 году наше правительство сжалилось над малым бизнесом и пустили в ход новую систему налогообложения, при применении которой, юрлица и ИП оплачивают один налог, вместо нескольких, что сильно облегчает жизнь. Правда, как я и говорил, облегчение это не для всех - для того чтобы иметь возможность применять УСН компания или ИП должны не вылезать за рамки некоторых ограничений:
  • Нельзя зарабатывать больше 15`000`000 рублей. Можно было просто написать млн. но нолики живее иллюстрируют цифру =)
  • В компании или у ИП должно быть меньше 100 наемных сотрудников.
  • Нельзя добывать или продавать полезные ископаемые (увы, поиски нефти на дачном участке отменяются)
  • Нельзя производить подакцизные товары (сигареты там, спиртное)
  • Организация не должна иметь представительств и филиалов. Вот это обстоятельство немного печально, поскольку даже маленький бизнес может быть территориально разрознен. Но, поскольку в нашем случае речь идет об ИП, тут печалиться не о чем - у ИП итак не может никаких представительств - только представители по доверенности.
  • Нельзя заниматься игорным бизнесом.
  • Есть еще какие-то ограничения, но я их не помню
Как видите все ограничения для нас пока совершенно заоблачны (правда, печально, что первое особенно заоблачно), что означает что УСН нам вполне разрешено.
 
Что же за единый налог мы должны будем платить? У "упрощенки" есть два варианта вычисления налогов. Правда, выбрать надо сразу и поменять форму расчета можно будет не ранее чем через 2 или 3 года - не помню.
 
Вариант первый: 6% от дохода юридического лица. Самый простой для калькуляции способ. Ежеквартально вы считаете сколько денег заработали, вычисляете 6% и относите их в сбербанк, заполнив соответственную квитанцию. Например, за квартал мы получим на наш расчетный счет 300`000 тугриков. Это означает что в налоговую мы отнесем 300`000*0,06=18`000. Не так уж и много, правда? Но это не много в том случае, если все 300 тысяч, или хотя бы большая их часть идет нам в карман. А если мы вынуждены платить за материалы, работу оутсорсерсеров и подрядчиков, аренду, бензин и т.д. Представьте, к нам на счет пришло 300 тысяч из которых 200 мы израсходовали на выполнение заказов. Получается что 18000 от нашей реальной прибыли составят целых 18%, то есть практически пятую часть всех наших доходов... По-моему это многовато. Что же делать в такой ситуации?
 
Если вы планируете заниматься бизнесом, который требует постоянных расходов на закупку материалов, субподряды и прочее (короче имеет высокие расходные статьи), лучше выбирать второй вариант УСН - 15% от дохода минус расход. Как это работает:
Весь квартал вы собираете документы о расходах относящихся к вашему юрлицу (товарные накладные, счета, договора). При вычислении налогов вы сначала суммируете всю прибыль, потом все расходы. Из суммы прибыли нужно вычесть сумму расходов и от полученной разности взять 15%, что и составит ваш налог.
 
ВНИМАНИЮ ИП! Не смотря на то, что вся прибыль считается собственными деньгами физического лица, налоговая не станет принимать в качестве расходных статей все его расходы. То есть чеки из продуктовых магазинов не относятся к расходам влияющим на размер налога. Для подтверждения юридической траты необходимы товарные накладные или прочие документы подтверждающие оплату, оформленные именно на ИП, а не на физическое лицо. Кроме того, даже если вы будете покупать все продукты питания в МЕТРО и нежно хранить товарные накладные, налоговый орган может отказать в их действительности, поскольку существует правило экономической целесообразности. Если по ОКВЭД вы продаете одежду, а налоги пытаетесь списывать документами на килограммы мороженного, то оправдать такие расходы будет крайне затруднительно.
 
Рассмотрим тот же пример:
За отчетный период на счет поступило 300 тысяч. При этом по документам у нас получается 200 тысяч расходов. Следовательно,наш налог составит (300000-200000)*0,15=15000. Ну вот, уже на 3000 меньше =) Разумеется все это очень бегло и для определения правильного варианта нужны более тщательные расчеты.
 
Итак, если вы выбрали вариант налогообложения который вам подходит, то надо просто распечатать Заявление о переходе на УСН (см. Образец заполнения заявления о переходе на УСН) и подать его в налоговую, вместе остальными документами, при регистрации.
ВАЖНО! При расчете налогов надо быть очень внимательными. Все ваши огрехи за год всплывут разом и могу оказаться очень неприятными. Согласно какому-то там постановлению, все компании работающие на УСН уплачивают налог ежеквартально, а отчетность сдают один раз - до первого апреля следующего за отчетным периодом года. Ну, короче за 2009 год отчетность надо подать до 1 апреля 2010.
Хэширование имен загружаемых файлов в Django, часть вторая

В прошлой реализации хранилища файлов с хэшированием имен файлы были доступны клиентам сайта по хэшированному имени, что не всегда удобно — файлы, передаваемые клиентам сайта, не имели осмысленных имён. Решая эту проблему, все хранилище было переработано и теперь представляет собой приложение. Кроме того, требуется дополнительно настроить frontend-сервер. Для начала несколько слов о самом принципе работы системы:
 Схема работы Django SHA1Storage:
  • 1. Клиент запрашивает файл у веб-сервера (frontend, в нашем случае это nginx).
  • 2. nginx перенаправляет запрос к Django (backend), согласно параметрам локации (location), которой соответствует URI запрошенного файла.
  • 3. Django принимает запрос, обрабатывает URL и возвращает nginx'у ответ с кодом 200, содержащий реальный путь до файла (в заранее заданной локации) в заголовке X-Accel-Redirect, а также тип содержимого файла в заголовке Content-type, основанный на расширении изначального имени файла.
  • 4, 5, 6. nginx обрабатывает путь в X-Accel-Redirect и в ответ на исходный запрос (пункт 1) клиента передаёт ему файл из директории, соответствующей локации, если файл найден. Заголовок Content-type, полученный от Django, при этом сохраняется.
Теперь обо всем по порядку. В первую очередь настроим frontend:
    server {
    listen mysite.ru:80;
    server_name mysite.ru www.mysite.ru;

# Нам совершенно не обязательно проксировать все запросы.
# Поэтому ограничиваемся проверкой запросов вида
# http://mysite.ru/media/upload/some_file.ext

# Передаём изменённый GET-запрос Django. В ответ мы должны получить ответ с
# заголовком X-Accel-Redirect.
    location /media/upload {
        rewrite ^/media/upload/(.*) /nginx/?filename=upload/$1 break;

        fastcgi_pass unix:/path/to/django's/fcgi.sock;
        include /etc/nginx/fastcgi_params;
    }
 

# Эта локация отражает реальный путь до директории хранилища наших файлов.
# Именно сюда Django будет ссылаться в X-Accel-Redirect.
# Прямой доступ к файлам клиентам сайта запрещён (для этого нужна директива internal).
    location /sha1storage {
        internal;
        alias /path/to/project/media/sha1storage;
    }

# Запрещаем  клиентам сайта прямые запросы к Django в локацию /nginx
    location /nginx {
        internal;
    }
 

# Запрещаем клиентам сайта прямой доступ к файлам хранилища в обход Django
    location /media/sha1storage {
        internal;
    }

# Локация с файлами, доступными для загрузки клиентам сайта не из sha1storage.
# Сюда Django перенаправит запрос посредством X-Accel-Redirect, если не
# найдёт файл в sha1storage.
    location /upload {
       internal;
       alias /home/www/www51/betalabs.ru/media/upload;
    }
}
Как это все в итоге работает: nginx получает запрос от клиента. Если путь запрашиваемого файла начинается с /media/upload/, то делается запрос к Django по адресу вида '/nginx/?filename=upload/filename.ext', с передачей в GET-переменной filename пути до файла, с указанием изначального имени. Обратите внимание, что в запросе к Django обрезается /media/, поскольку Django всегда работает с файлами внутри директории, указанной в MEDIA_ROOT.
 
Для настройки django нам понадобиться приложение SHA1Storage.
 
ВНИМАНИЕ. На данный момент приложение находится в стадии beta-тестирования и имеет некоторые ограничения в настройке, которые, я надеюсь, в ближайшее время будут ликвидированы. Если вы найдете какие-то баги, буду очень благодарен за багрепорт.
 
Для установки добавляем его в INSTALLED_APPS:
 
INSTALLED_APPS = (
    'sha1storage',
)

# Если хотите использовать это хранилище как основное, можно указать параметр DEFAULT_FILE_STORAGE.
DEFAULT_FILE_STORAGE = 'sha1storage.storage.SHA1FilenameFileSystemStorage'
 
Если вы хотите использовать хранилище только для отдельных файлов, то к полю файла в модели необходимо добавить свойство storage.
 
В urls.py необходимо добавить обработку URL обработчика sha1storage:
urlpatterns = patterns('',
 (r'nginx/', 'sha1storage.views.get_real_filename'),
);
В принципе это все. Теперь при загрузке файла его имя будет хэшироваться, и он будет сохраняться в папку /path/to/project/media/sha1storage/upload_to_mode_field_path/. При этом модели будет передаваться не хэш от имени файла, а само имя. Из дополнительных особенностей: все файлы, кроме стандартной графики, sha1storage возвращает с заголовком Content-Disposition: attachment, в качестве полумеры для закрытия XSS-уязвимостей, пока не реализованы более строгие алгоритмы защиты.
Регистрируем ИП или первый шаг к своему делу

Помимо программирования, я планирую писать в блоге и о юридических аспектах своей жизни, поскольку они составляют немалую ее часть. Писать я буду стараться максимально просто, именно в ключе практического применения. Собственно, одна первая статья из этой серии у меня уже есть - это кратенький рассказ-жалоба на "Ваше право". Я думаю, про то, как вести себя с такого рода "посетителями", я напишу дополнительно. Сейчас же я хочу поделиться опытом регистрации себя в качестве Индивидуального Предпринимателя. Зачем это нужно? Ну, во-первых, это упрощает взаимодействие с некоторыми клиентами, поскольку при наличии ИП мы можем заключать договора Юрлицо-Юрлицо, а к таким договорам у многих клиентов больше доверия. Во-вторых, это вообще легализует деятельность в качестве оутсорсера. Конечно, можно фрилансить и без всяких ИП, однако, при постоянном извлечении прибыли от оказания услуг, налоговая может трактовать это как незаконное предпринимательство, даже если вы ежегодно подаете декларацию о доходах.
Строго говоря, решение об открытии ИП - это вопрос сугубо личный, и как-то склонять к этому я не собираюсь, тем более, что переход к официальному предпринимательству накладывает ряд дополнительных обязательств. Поэтому я буду писать не о том, зачем, а о том как это делается.
Вообще, налоговая история человека начинается с получения им Индивидуального Номера Налогоплательщика - ИНН. Вполне вероятно, что у вас такого документа как раз и нету. В принципе, начать регистрацию можно и без него, но в процессе все равно придется получать. Поэтому я рекомендую, для тех кто пока не встал на учет в налоговом органе, сделать это, как говориться, в первую голову. Благо, процедура совсем простая и безболезненная. Для начала вам надо узнать, где располагается ваше районное отделение налоговой. Лучше всего воспользоваться формой на официальном сайте налоговой - http://service.nalog.ru:8080/addrno.do.
ПРЕДУПРЕЖДАЮ. Форма может глючить. Во всяком случае, в Firefox3.5@Ubuntu глючит - после второго шага (выбор региона) сразу выводит реквизиты центрального отделения по всему региону, без уточнения адреса. Побороть глюк можно, нажав кнопку "назад", а потом сразу "дальше", хотя в других браузерах, возможно, и нет глюков или есть, но другие. В любом случае, поборов эту форму, вы получите адреса или телефоны, которые нам нужны и для получения ИНН, и для подачи документов на регистрацию.
ИНН делается за один день - пришли, отдали паспорт, подождали, получили - так что это самая простая из предстоящих нам операций.
Итак, после получения ИНН можно смело приступать непосредственно к подготовке нашего основного визита в налоговую. Первое, что нам предстоит, так это заполнить заявление по форме p21001. Вот бланк самого заявления, и вот Образец заполнения. На последнем листе необходимо указать список видов деятельности, которыми вы собираетесь заниматься - так называемые коды ОКВЭД. Найти справочник в сети не проблема, но лично мне понравился больше всего getokved.ru. Все, что касается околокомпьютерной деятельности, описывается в разделе 72:
  • 72.1 Консультирование по аппаратным средствам вычислительной техники
  • 72.2 Разработка программного обеспечения и консультирование в этой области
  • 72.3 Обработка данных
  • 72.4 Деятельность по созданию и использованию баз данных и информационных ресурсов
  • 72.5 Техническое обслуживание и ремонт офисных машин и вычислительной техники
  • 72.6 Прочая деятельность, связанная с использованием вычислительной техники и информационных технологий
Более подробную расшифровку кодов можете найти все на том же сайте, конкретно тут.
Если вы обратили внимание, в заявлении на всех страницах в правом верхнем углу указывается номер листа. Но на листе с видами деятельности поле с номером пустое, и его нужно заполнить. Все дело в том, что на странице всего 10 полей для кодов, но закон никак не ограничивает вас в количестве видов деятельности. Следовательно, вы можете приложить к заявлению несколько таких листов, соответственно последовательно их нумеруя. Так же стоит обратить внимание, что основным видом деятельности будет считаться код, который указан первым. Если честно, я не знаю зачем вообще выделяется основной вид деятельности, но так или иначе, этот факт стоит учитывать - на всякий случай.
ВАЖНО! После заполнения всех кодов, не забудьте указать их количество на первой странице заявления.
Еще нам может пригодиться заявление о переходе на Упрощенную Систему Налогообложения - УСН. О том, что это такое и с чем его едят, я напишу отдельно, в ближайшее же время. Там же и выложу бланк заявления с образцом.
Кроме этих двух заявлений (или одного, если вы решите не переходить на УСН, что маловероятно), нам понадобится квитанция об оплате госпошлины в размере 400 рублей. Реквизиты для платежа вы можете узнать по телефону или в интернете. Правда, как это ни странно, на сайте налоговой я этих данных не нашел - у них вообще поиск периодически падает с ошибкой "#1040: Too many connections". Для всех москвичей реквизиты одинаковые, поскольку регистрацию всех ИП, ООО и прочих осуществляет ИФНС №46. Для удобства выкладываю Бланк квитанции и Образец заполнения квитанции, который заполнен реквизитами для москвичей.
ВНИМАНИЕ! Если вы будете использовать заполненную квитанцию, ОБЯЗАТЕЛЬНО уточните и проверьте реквизиты платежа - они могут измениться в любой момент.
Итак, теперь можно печатать все наши документы и перемещаться в банк и к нотариусу - в произвольном порядке. Оплачивать квитанцию можно в любом банке, но лучше всего в Сбербанке, потому как в других может быть комиссия за оплату. Нотариус подойдет любой - от него нам требуется заверение нашей подписи на третьей странице нашего заявления.
КСТАТИ. Расписываться дома на третьей странице строго запрещается - это можно делать только в присутствии нотариуса, иначе не заверит. Вообще, лучше нигде в заявлении не расписываться - нотариус скажет, где и как подписаться.
Мне такое заверение обошлось в 500 рублей, хотя цифра эта у разных нотариусов может и отличаться. Я особо не парился, и просто сходил к ближайшему.
Кстати, где-то в процессе всех этих кувырканий, нам надо сделать копию ИНН и паспорта. Из паспорта нам надо два разворота - с основными паспортными данными и с пропиской.
КСТАТИ. Копию паспорта лучше делать на одном листе, иначе придется сшивать два листа, заклеивать с обратной стороны место скрепления бумажкой, расписываться на ней так, чтобы часть росписи попадала на бумажку, а часть на основной лист и писать "Прошито и пронумеровано 2 листа". В заявлении за вас это сделает нотариус, а тут придется возиться самостоятельно. Так что уж лучше постараться и сделать оба разворота паспорта на одной бумажке. Лично я просто отсканировал, склеил в GIMP и распечатал.
Теперь мы имеем полный комплект документов, необходимых для превращения из Человека Разумного в Человека Предприимчивого - паспорт, копию паспорта, копию ИНН, заявление о регистрации, заявление о переходе на УСН (ежели собираемся переходить) и оплаченную квитанцию. Осталось передать эти документы уполномоченным органам и ждать 5 рабочих дней. На самом деле, в законе написано не более пяти рабочих дней, однако, согласно какому-то там письму "О не сокращении сроков", налоговая использует отпущенный срок полностью, якобы для уменьшения количества ошибок при оформлении.
Подача документов в Москве происходит следующим образом. Первым делом необходимо прибыть по адресу: Москва, Походный проезд, владение 3, корп.1. Как проехать - описывать не буду, думаю, все мы умеем пользоваться гугл-яндекс-картами. По прибытии нам необходимо отыскать корпус 1, подъезд 3. Это уже сложнее, поэтому прилагаю схему «ИФНС №46» на Яндекс.Картах.
Нам нужен зал №4 - это который направо (налево зал №3, который нам пригодится позже). В четвертом зале располагаются веселенькие терминалы регистрации в электронной очереди. Если возле них вдруг не обнаруживается приветливый юноша или знойная барышня, придется самостоятельно отыскать кнопку D. Автомат плюнет в нас чеком с циферками DХХХ, вместе с которым мы уютно располагаемся на любезно предоставленных стоячих местах. Сидячие, в принципе, тоже присутствуют, но сомневаюсь, что кто-то нам уступит. Разнообразить томительную очередь можно, наблюдая за движениям электронной очереди, красочно  - в двух цветах - иллюстрируемую на множестве табло. Как только очередь соизволит дойти до нас, внимательно запоминаем номер окошка и торопимся в зал №3. Там, отыскав нужный номер, мы встретим ясную приветливую мину... Нежно улыбаемся в ответ и передаем паспорт, чек с номером и пакет документов в руки ответственного работника.
КСТАТИ. Перед тем как проникать в зал №3, лучше выключить свой мобильный телефон - по правилам в залах ИФНС разговаривать по телефону нельзя. Да и опасно: охранники в третьем зале зверские - ругаются и хамят.
Пару минут спустя нам вернут паспорт, заставят подписать расписку о вручении, подарят копию этой расписки и, одарив лучезарной улыбкой, отпустят с миром. Теперь можно заглянуть в туалет, перекусить в столовой и отчаливать в родные пенаты. Впереди нас ожидает пять дней релаксации.

После дождичка в четверг.

По истечении отпущенного налоговикам срока в размере пяти рабочих дней, нам необходимо совершить еще один набег на их логово. Лично я прибыл на место дислокации примерно в 14:30, снова получил плевок от агрегата (на этот раз при нажатии кнопочки M). Номер тут же появился на табло и я проследовал к нужному окну. Индифферентный молодой человек просмотрел мой паспорт, забрал расписку и, взяв три подписи в каком-то акте, выдал мне мои документы - Свидетельство, выписку из ЕГРИП и уведомление о постановке на учет. Вот и все - в общей сложности я пробыл в налоговой три минуты одиннадцать секунд. Вышел я уже преобразившийся в Человека Предприимчивого.
 
Как видите, процедура достаточно проста и не очень обременительна. Правда, если вы переходите на УСН, еще надо будет появиться в районной налоговой, чтобы получить еще одно уведомление о постановке на учет по упрощенке. Но это придется делать не сразу - по закону налоговая может делать это уведомление в течение месяца. Так что, прежде чем ехать, обязательно позвоните и уточните состояние дел. Еще нам предстоит побывать в пенсионном, открыть счет в банке и начать вести деятельность. И, конечно, бухгалтерия, куда без нее. Обо всем этом я обязательно напишу... постепенно =)
Яндекс крутит гайки

Когда экономическое состояние плохое, то говорить о продвижении, развитии, науке — пустая болтовня.
(с) И. Я. Франко

О том что Яндекс поменял алгоритм знают уже все. Причем шум вокруг нового алгоритма не утихает до сих пор - очень уж сильно изменилась выдача. Много социального контента попало в топ, много коммерческого вылетело. Сам я не СЕО-шник, но хочу поделиться впечатлениями от происходящего не как айтишник, а как владелец интернет-магазина, активно продвигаемого в своем сегменте.
 
К новому году мы начали готовиться за нескольку месяцев. Набор стандартный - статьи для веса и биржи для скорости. Биржи были запущены примерно в начале-середине октября (как раз незадолго до смены алго), а статьи чуть позднее - ближе к концу октября. Все шло как положено - вылезли мы по основным запросам в топ 3, повесели несколько дней и вот тут-то все и началось.
Сразу после смены алгоритма мы уехали на вторую страницу по основным запросам и потеряли по 2-3 позиции в низкосастотниках. Причем, это отразилось в основном на "свежих" ключевиках, а старые наши слова практически и не покачнулись. Ссылки у нас были довольно качественные - не с говносайтов, следовательно яндекс увеличил значимость возраста ссылок. Собственно, особенно предпринимать было нечего, так что мы просто тихо наблюдали за развитием событий. Через какое-то время низкочастотники вернулись в норму и чуть-чуть прибавили основные запросы - это доиндексировались статьи. И на этом всякие эвалюции закончились и до топа по основным запросам мы не доползли. =\
 
Среди СЕОшников сейчас бытует мнение, что Яша специально мутит воду коммерческим сайтам (запускает соцресурсы в топ по явно коммерческим запросам, например), чтобы втянуть больше игроков в Директ. Что ж, вполне реалистично звучит. Мы в директ решили не лезть, поскольку оставшийся трафик с низкочастотников и основных запросов нас пока более-менее удовлетворяет, но вот многие кто вылетел из топа вынуждены теперь тратить деньги на контекстную рекламу.
 
PS: Тут с неделю назад подал заявку на платную регистрацию в ЯК - все давно собирался. До сих пор не рассмотрели, хотя должны обрабатывать за сутки. В саппорте извиняются и просят подождать. Сдается мне, что многие ломанулись не только в директ, но и в платный каталог, да так что менеджеры не справляются. Так что, если в яндексе хотели заработать на смене алгоритма, им это явно удалось.
jQuery, :hidden и тэг option

В jQuery имеет место одна проблема с псевдоцсс селектором :hidden - в браузерах отличных от FireFox конструкция вида
 
<script>
$(document).ready(function() {
	$("*:hidden").remove();
});
</script>
 
удалит не только действительно невидимые объекты, но и все options.
Проблема кроется в текущей реализации алгоритма определения видимости:
Sizzle.selectors.filters.hidden = function(elem){
	return elem.offsetWidth === 0 || elem.offsetHeight === 0;
};
 
Фаерфокс этот момент обрабатывает вполне корректно - в качестве габаритов option он всегда возвращает размеры отрисованного select. А вот остальные браузеры (возможно не все конечно, но основные) сплоховали - всегда возвращают 0, что и приводит jQuery в замешательство.
 
В принципе есть два варианта решения данной проблемы. Первый сгодится если проблемы возникают только с вашим кодом - тут можно просто изменить конструкцию селектора:
 
<script>
$(document).ready(function() {
	$("*:hidden:not(option)").remove();
});
</script>
 
Хуже если эта проблема мешает работе каких-либо плагинов. Решить ее можно "подменив" селектор ":hidden", что, между прочим, совсем не сложно.
 
<script>
// Удалять настоящий селектор не за чем.
// Просто переименуем его в :realhidden.
jQuery.expr[':'].realhidden = jQuery.expr[':'].hidden;
// А на его место поместим наш собственный, с дополнительной проверкой
jQuery.expr[':'].hidden = function(elem) {
	// Если обрабатываемый элемент это option возвращаем false
  	if (elem.nodeName == "OPTION") {
		return false;
  	} else { // Если нет - передаем управление оригинальному селектору :hidden 
 		return jQuery(elem).is(":realhidden");
	}
};
$(document).ready(function() {
	// Сработает функция jQuery.forceHidden и все опции останутся на месте
	$("#test :hidden").remove(); 	
});

</script>
 
Главное, чтобы замена селектора произошла до выполнения кода скрипта, который будет ее использовать. Скорее всего достаточно того, что он выполняется до события $(document).ready, но в некоторых случаях могут быть варианты - просто будте внимательный.
Почему я редко пишу в блог

Лучшее враг хорошего
(c) народная пословица

Есть у меня одна проблема с подбором материала - мне все время кажется, что выбранная мной тема будет не нужна и не интересна. Либо, кто-то это уже точно написал, либо она вообще не достойна опубликования. Из-за этой проблемы прерывались мои неоднократные попытки вести блоги на блогосервисах, и из-за нее же я не публикую, и вообще не описываю, большинство из своих наработок. Причем, я отлично знаю, что в десятках блогов разбирают одни и те же проблемы, разбирают одни и те же решения и все такое прочее. Но сам, почему-то, не могу - только если себя заставлять. А написанное через силу вряд ли вообще будет читабельно. В чем корни моей проблемы я, увы, пока не нашел, однако я стараюсь бороться с ней, потому что понимаю - хоть я и не очень крутой программист, но у меня есть чем поделиться и о чем рассказать. И я буду стараться рассказывать. Я очень надеюсь, что постепенно в этом блоге появятся постоянные читатели, которым будет интересно и полезно. И надеюсь они будут задавать вопросы - мне всегда было легче отвечать на вопросы, чем упреждать их своевременным описанием - вопрос для меня как катализатор. 
jQuery abeInline plugin

Я наконец оформил одну из функцию, которую написал в процессе разработки этого блога, в виде плагина к jQuery. Получился плагин abeInline - средство для inline редактирования контента. Конечно, пока она еще не полная, так сказать beta-версия, но в принципе работоспособная. Сейчас она умеет конвертировать блоки в text input и в textarea, отправлять результат по AJAX и обрабатывать несколько разных блоков как единую форму.
 
Документация - тоже пока не полная =(
Скачать - пока выложил только на jQuery, но планирую сделать проект на code.google.com с ропозиторием и багтреком.
Лицензия - библиотека распространяется по Лицензии BSD.
 
Если честно, это первая библиотека открываемая мной публично. У меня есть одна черта, которая мне очень мешает в вопросе выкладывания своих наработок - мне все время кажется что работа настолько незакончена, что выкладывать ее неприлично. Помимо всего прочего, это распространяется и на запуск личных проектов - многие я не запустил именно потому, что они казались мне не готовыми. Сейчас я усердно борюсь с этими своими ощущениями - в конце концов, полевые испытания всегда самые эффективные. А если что-то в библиотеке не работает - никто же не отменял багтрекинг, патчи и новые версии. Вобщем, теперь я буду стараться выкладывать больше своих наработок - возможно кому-то что-то из них поможет.
Подсветка синтаксиса, часть четветрая, заключительная

Ну вот , кажется, и походит к концу моя эпопея с подсветкой синтаксиса. В процессе беседы, несколько для меня неожиданной, с Иваном Салагаевым, получил от него несколько разъяснений по его библиотеке и сам покопался в ней поглубже. В итоге, убрал из функции инициализации автоматический поиск блоков для подсветки и открыл функцию highlight для внешнего доступа. Кое-какие недочеты конечно остались, но я думаю разберусь со временем. Ивану огромное спасибо за библиотеку и за помощь.
 
Еще добавил вывод номеров строк, но он работает независимо от основной библиотеки.
Подстветка синтаксиса, часть третья

Задумался о том, что в текущей реализации подсветки кода я могу столкнуться с чрезмерным увеличением количества AJAX-запросов. Учитывая что на одной странице выводится до 20 записей, в каждой из которой может оказаться по несколько блоков кода, это чревато десятками запросов.
 
В сети я нашел несколько скриптов для подсветки синтаксиса на JavaScript, однако, после нескольких экспериментов, я убедился что они не дают никаких реальных преимуществ. Самым качественным решением, из тех которые я нашел, является библиотека Ивана Салагаева (http://softwaremaniacs.org/soft/highlight/). Но, во-первых, упакованная библиотека со всеми языками весит 78 Килобайт, а во-вторых, имеет несколько странную реализацию - подсветка осуществляется ТОЛЬКО автоматически, основываясь на анализе кода, то есть нельзя вручную указать какой блок подсвечивать. Скорость его работы я не анализировал, поскольку для меня достаточным для отказа фактором стал именно вес библиотеки.
 
Поэтому я несколько оптимизировал свою систему. В новой версии все блоки на странице обрабатываются одним AJAX запросом. Для этого сначала генерируется форма, в которую агрегируются все блоки с кодом. Форма создается по правилам Django Formset, для удобства ее обработки на сервере.
Полученный от сервера ответ разбит на блоки, которые очень легко разбираются и размещаются где положено.
 
$(document).ready(function() {
	var form = $("<form>"); // Создаем форму.
	var i = 0;
	$(".highlight").each(function() { //Перебираем все блоки требующие подсветки
		var hObject = $(this);
		hObject.attr("id", "highlight-"+i); // Присваиваем блоку уникальный id, чтобы потом найти его.
		// Создаем поле language для формы. Содержит название языка.
		language = $("<input>").attr({
			"name" : "form-"+i+"-language",
			"value" :  hObject.attr("lang")? hObject.attr("lang") : "text", // Если аттрибудет lang не задан, код будет возвращен без подсветки.
			"type" : "text"
		});
		// Создаем поле id для формы. Используется для идентификации блока с результатом.
		id = $("<input>").attr({
			"name" : "form-"+i+"-id",
			"value" :  i,
			"type" : "text"
		});
		// Создаем поле code для формы. Содержит код для подсветки.
		code = $("<textarea>").attr({
			"name" : "form-"+i+"-code",
		}).text(hObject.html());
		// Добавляем поля к форме.
		form.append(language);
		form.append(code);
		form.append(id);
		i++;
	});
	// Если есть хотя бы один блок
	if (i) {
		// Создаем поле form-TOTAL_FORMS. Нужен для Django Formset для обработки формы. 
		total = $("<input>").attr({
			"name" : "form-TOTAL_FORMS",
			"type" : "text",
			"value" : i
		});
		// Создаем поле form-INITIAL_FORMS. Нужен для Django Formset для обработки формы. В нашем случае всегда 0.
		initial  = $("<input>").attr({
			"name" : "form-INITIAL_FORMS",
			"type" : "text",
			"value" : "0"
		});
		// Добавляем поля к форме.
		form.append(total); 
		form.append(initial);
		// Отправляем запрос 
		$.post("/tools/highlight/", form.serialize(), function(response_data) {
			// Перебираем блоки ответа.
			$(response_data).find(".highlighted").each(function(){
				// Заменяем исходный блок, на подсвеченный, ореинтируясь на id.
				$("#highlight-"+$(this).attr("id")).replaceWith($(this).html());
			});
		});
	}
});
Планы по ABE

Решил записать ближайшие планы по развитию AbendBlatt Engine:
  • Хочу добавить поддержку переводов для постов. Чтобы один пост можно было писать на разных языках и, при наличии переводов, выводить ссылки вида "Read in English". Лично я не думаю что сразу начну этим пользоваться, однако это может оказаться полезным в будущем. Естественно, к этому необходимо прикрутить систему автоматического определения языка пользователя и хотя бы возможность выбрать язык по умолчанию.
  • Нужно добавить к постам возможность указания связанных записей. Во-первых это просто удобно, а во-вторых, учитывая что многие темы невольно разделяются на несколько частей, это необходимо для формирования цепочек.
  • Нужно доделать систему оповещений и подписки. Сейчас она функционирует через пень-колоду.
  • Экспорт RSS надо сделать более гибким. В первую очередь надо сделать отдельные ленты для колонок. Кроме того думаю сделать интерфейс для создания собственных сборок - например, если кто-то захочет ленту состоящую из нескольких колонок, но не всего блога.
  • Еще хочу сделать систему формирования выпусков. Под выпуском я подразумеваю некий связный набор постов. Причем с возможностью использования как уже опубликованных материалов, так и черновиков. Основная особенность выпуска в том, что он выводится как одна статья (с постраничным разбиением по контенту) и может быть скачана в видел PDF.
PS: Ну, и естественно, в приоритетном режиме надо доделывать основные административные интерфейсы. Поскольку сейчас многие операции я проделываю напрямую в базе или через shell django-проекта.
Подсветка синтаксиса, часть вторая

Мои эксперименты так важны, так прекрасны, так удивительны, что я с трудом могу оторваться от них, чтобы поесть.
(с) Н. Тесла

Как я и думал, встраивание подсвеченного кода в пост в чистом виде оказалось решением скверным. Причем, помимо неудобств при редактиваронии, такой подход вызывает дополнительные проблесмы при экспотре RSS - лишние теги + лишние стили... ничего хорогошего вобщем. =)
 
В итоге я заменил способ подстветки - теперь это работает так:
 
В WYSIWYG вставляется контейнер с небработанным кодом, которому присваивается класс highlight и в аттрибуте lang указывается язык для подсветки. По окончании загрузаки страницы, из всех контейнеров класса highlight извлекается их содержимое и AJAX-запросом отправляется на сервер, а полученный результат замещает собой первоначальный контейнер.
 
Выполнено это пока не очень изящно, однако работает.
 
$(document).ready(function() {
	$(".highlight").each(function() {
		var hObject = $(this);
		$.post("/tools/highlight/", {
			"language" : hObject.attr("lang")? hObject.attr("lang") : "text",
			"code" : hObject.html()
		},
		function(response_data) {
			hObject.replaceWith($("<div>").append(response_data));
		});
	})
});
Хэширование имен загружаемых файлов в Django

Уже давно я столкнулся в Django с проблемой загрузки файлов, с utf8 символами в названии. При сохранении такого файла django рушилась с руганью на ошибку конвертации ascii строки. Однако тогда разбираться с проблемой я не стал за ненадобностью - мне было проще переименовывать редкие файлы с utf8 именами.
 
А вот сейчас проблема эта всплыла опять и достаточно остро. За советом как лучше поступать с utf8 в именах файлов я обратился к хорошему сисадмину, который посоветовал мне вообще отказаться от сохранения юникода. Это чревато рисками обхода ограничений директории и получения доступа к исполняемым файлам системы.
 
"Дело в том, что из-за отсутствия гарантий однообразности восприятия специальных символов в имени файла, одни функции в системе могут счесть имя файла валидным и безопасным, а другие - иначе интерпретировать некоторые символы, в результате чего есть опасность нарваться на "../../../filename" в аргументах системному вызову, со всеми вытекающими." © Arach
 
Поэтому, было решено просто хэшировать имена загружаемых файлов. Есть в этом конечно и минус (при скачивании файла несколько не удобно будет его идентифицировать), однако на данном этапе так будет лучше. А уж в процессе подумаю о решении и этой проблемы.
 
Изменить метод работы с файлами в Django очень просто - достаточно сделать специальный обработчик - подкласс django.core.files.storage.Storage. Мало того, в случае лишь частичной замены методов работы, можно наследовать стандартные дочерние классы.
 
# -*- coding: utf-8 -*-
from django.core.files.storage import FileSystemStorage
from hashlib import sha1

class SHA1FilenameFileSystemStorage(FileSystemStorage):
	def get_valid_name(self, name):
		type=""
		if name.rfind("."):
			type = name[name.rindex("."):]
		return str(sha1(name.encode("UTF-8")).hexdigest())+type
 
В данном случае я наследовал стандартный класс хранилища файлов FileSystemStorage, переопределив в нем всего один метод. Метод get_valid_name отвечает за генерацию валидного имени файла ДО проверки доступности такого имени для сохранения. Сначала мы пытаемся отделить расширение файла, если таковое есть, после чего хэшируем входящее имя и прибавляем к нему расширение. Лично я предпочел установить этот обработчик в качестве стандартного в своих приложениях, для чего в settings.py определяется переменная DEFAULT_FILE_STORAGE.
 
import django_useful
DEFAULT_FILE_STORAGE = 'django_useful.sha1storage.SHA1FilenameFileSystemStorage'
Если же надо применить данный обработчик только к определенным файлам, нужно в модели передать путь  его в качестве аргумента storage
 

from django.db import models
import django_useful

class Car(models.Model):
    photo = models.ImageField(storage=django_useful.sha1storage.SHA1FilenameFileSystemStorage(location='/media/photos'))
 
PS: Сегодня добавил в блог подсветку синтаксиса с помощью Pygments. Реализовал в виде плагина для FCKEditor, но пока не очень изящно - код со стилями и прочей ересью вставляется прямо в пост. Не очень удобно редактировать - фактически приходится заново генерировать код полностью. Думаю что лучше будет заменить это все на вставку некого плейсхолдера, и генерировать код непосредственно перед выводом, с помощью PreView триггера.
Pisa XHTML2PDF и поддержка HTTP AUTH

В рамках Торговой Системы понадобилось мне сделать генератор этикеток и ценников. Мой старый, генерировавший jpg картинки по строгому шаблону не годится, потому что информация на разхных ценниках разная, сответсвтенно и размеры у них должны быть динамические. Наиболее быстрым и удобным решением, мне показалось генерировать pdf. В процессе размышлений и поиска, была найдена библиотека Pisa, конвертирующая html в pdf. Вот это совсем то что нужно. Само собой есть определенные ограничения в верстки, но главное она понимает большую часть html+css.
 
Все было неплохо, пока не наткнулся на 2 момента. Момент первый - если картинка вставляется в ячейку таблицы, у которой задан конкретный размер, то картинка эта отображается только в том случае, если у нее заданы аттрибуты width и height. То есть встраивать картинки с неопределенным размером в таблицу не получается. Поиски по комьюнити ничего не дали, поэтому полез в исходники. В итоге обнаружилось следующее - в методе определяющем парметры картинки, в случае отсутствия жестко прописаных размеров, основным источником размеров почему-то считался родительский объект. То есть, если у картинки не заданы размеры, то Pisa пытеатся взять эти размеры у контейнера в котором этак картинка лежит. Если размеры родительского контейнера не прописаны в стилях, то все проходит более-менее нормально - Pisa, не получив от родительского объяекта объявления стиля вычисляет размеры картинки исходя из самой кратинки. А вот, если у родительского контйнера в стиля присутствует width или height, то тогда размеры картинки вычисляются именно их этих параметров. Причем делается это без конвертации значений, из-за чего, собсвтенно и существует проблема. Поскольку, в стилях размеры пишутся с указанием единиц измерения (в моем случае ячейка имела ширину 7cm), заначение это строковое. И естественно, умножение его на 96 dpi (именно так происходит "вычисление" размера картинки), естественно дает на выходе 0. Патчить это я не стал - решил ограничиться вычислением размеров картинки при генерации html шаблона, и указанием их в аттрибутах тега <img> - ИМХО, это наиболее верное решение.
 
А вот вторую проблему без патча решить не удалось. Связана она опять-таки с картинками. Pisa поддерживает два варианта обращения к картинкам - либо по абсолютному пути на сервере (для локальных файлов, естественно), либо по http или https. Однако при этом не была учтена особенность, что урл может быть защищен http-авторизацией. У меня все dev-площадки всегда закрыты от внешнего доступа. Да и некоторые рабочие системы тоже. Поэтому, снова пришлось лезть в исходники, но на этот раз патчить все-таки пришлось. Патч обеспечивает обработку URL вида protocol://userid:passwd@host/path/to/file. То есть перед тем как запросить с сервера host файл /path/to/file система посылает Basic Auth заголовок с логином и паролем для доступа.
 
Патч сделан для версии XHTML2PDF / pisa 3.0.32
 
PS: Пока копался в коде пизы, понял что в ближайшем будущем буду от нее отказываться - не устраивает архитектра и перегруженость. Слишком много не нужного в рамках проекта ТС функционала.
ЦЗППиП "Ваше право" - презумпция виновности

Пришли к нам в магазин недавно две женщины. Назвались какими-то именами, показали какие-то документы и заявили что они из Общественной Организации "Ваше право". Показали девочкам нашим некое направление и собрались проводить какую-то проверку. Ни меня, ни Саши в магазине не было, а девчонки, само собой, растерялись. Позвонили нам, но по телефону трудно было в ситуации разобраться что к чему, поэтому проверку они провели, составили даже какой-то акт. В акте этом значилось несколько нарушений, не сказать что очень серьезных. Все их нам перессказли по телефону при этом объявив, что их организация не штрафующая, но зато они акт этот передают в вышестоящие инстанции. Помолчав с полминуты, они объявили что возможны, варианты... сотрудничества. В качестве варианта было предложено оказать их организации посильную помощь в размере семи с половиной тысяч рублей. Увы, поскольку понимания ситуации не было, помощь таковая была оказана, в чем одна из продавщиц даже расписалась, но никакого документа о получении денег, разумеется, не получила.


АКТ
 
Акт оказался бумажкой весьма забавной. Подробно описывать ее не буду, но фиктивность данного документа видна была невооруженным глазом. Бумага эта предписывала нам в пятидневный срок записаться на прием к юристу данной организации, для получения разъяснений по нарушениям, указанным в акте. Как выяснилось, посещение после проверки "бесплатное". Поскольку деньги, на которые нас чистой воды развели (я бы сказал как лохов), вернуть все равно уже было невозможно, было решено посетить данное заведение, послушать что расскажут нового.
 
Офис ЦЗППиП "Ваше право"
 
Судя по тому, что офис компании... простите, общественной организации, находится в практически в самом центре Москвы, жертвуют этой конторе не мало. Приехали мы к ним в гости, приняла нас их юрист и дала разъяснения. Кое-что оказалось действительно полезным, отрицать не буду. Однако! После консультации, нам снова было объявлено, что далее акт пойдет по инстанциям. Вот вам и добровольное пожертвование... Естественно, я осведомился, есть ли варианты обойтись без инстанций. Собственно, этого вопроса от меня и ждали - сначала уточнили, вносили ли мы что-либо, после чего, уточнив можем ли мы так сказать расширить сумму пожертвования (я на всякий случай ответил что можем), предложили два варианта - внести сейчас же или перечислить им на счет. Поскольку вносить наличные деньги я отказался категорически, мне была выдана квитанция для оплаты с пустым полем "Сумма". Чтобы эту цифру как-то очертить, я осторожно спросил, какая сумма рекомендуется к пожертвованию. Намек в ответе был весьма недвусмысленный: "Ну, мы не можем рекомендовать ничего. Сами смотрите. За аренду мы платим сто тысяч в месяц. Вот вы можете взять на себя небольшую часть этой суммы. Например, судебные издержки, если бы мы подали на вас в суд, составляли примерно тридцать тысяч... Вы когда перечислите, позвоните."
 
Итого
 
Разумеется, никаких денег мы им не перевели и не собираемся. И первый-то раз не надо было, но там, увы, недостаток информации сыграл на руку этим легализованным мошенникам.
Но как и во всем, в этой ситуации тоже есть положительные стороны - нам указали на все ошибки нами допущенные, нам дали разъяснения по некоторым пунктам закона, в которых мы сам так и не разобрались. Ну и вообще - "Пока гром не грянет, мужик не перекрестится" (с).
 
PS: А еще это форсировало разработку собственной Торговой Системы. Тоже, Django-based.
Забег

Десять тысяч - и всего один забег
Остался.
В это время наш Бескудников Олег
Зазнался.
Я, говорит, болен, бюллетеню, нету сил!
И сгинул.
Вот наш тренер мне тогда и предложил:
Беги мол.

Завтра в подмосковном Королёве пройдет XXXIII (кажется) "Космический марафон". Кроме самого марафона (42 км 195 м) будут забеги на 3, 10 и 20 километров.

 
Бегать я начал совсем недавно, так что решил поучаствовать в забеге на 10 километров, хотя по последним тренировкам, чувствую что сил достанет и на 20. Но папа рекомендует не рисковать зря. В конце концов, марафоны такого плана проходят достаточно часто, так что еще успею. Сам-то он бежит марафон, причем уже второй за эту осень - 13 сентбяря он бегал на Московском Международном Марафоне Мира.
 
Самое трудное во всем этом мероприятии - добраться до Королева, а потом выбраться обратно. Старт назначен на 11, так что приехать в худшем случае надо минут за 1:20 до старта - за час до старта уже надо проходить регистрацию. Сначала нас обещался подвезти мой друг, но, как с ним это в последнее время случается все чаще, в последний момент сослался на занятность и отказался. Так что завтра будет весело =) Метро-Электричка-Марафон-Электричка-Метро.
 
В любом случае, не сомневаюсь что это будет увлекательно. После финиша (а я планирую пробежать свои 10000 быстрее часа), мне придется еще не меньше трех часов ждать пока финиширует папа. Попробую устроить на него фотоохоту. Жаль, не получится взять с собой хорошую камеру - сдавать аппарат стоимостью в полсотни тысяч, да еще и с оптикой, в камеру хранения не очень хочется. Ничего, старый добрый Lumix FZ-5 по прежнему дает 12-ти кратный зум и 5-ти мегапиксельные снимки, так что не пропадем.
Новый день, новый шаг

"Ну и вопрос! Это, знаешь, как у верблюда спросили:
«Почему у тебя шея кривая?» Так он ответил: «А что у меня прямое?»"
(с) Богдан Архипович Гайдай
(с) Волны гасят ветер
(с) А. и Б. Стругацкие

Сегодня добавил в блог базовую регистрацию. Зарегистрироваться в системе теперь можно, но вот редактирование профиля пока не работает. Параллельно с этим, добавил поддержку комментариев, тоже в самом простом варианте пока - без форматирования.
 
Никак не могу решить, нужна ли в комментариях поддержка ответов - построение древовидной структуры. В некоторых блогах это есть, а в некоторых нету. Количество плюсов-минусов для каждого варианта лично для меня представляется примерно одинаковым, хотя возможно я чего-то не понимаю. В любом случае комментирование подлежит капитально доработке, а начать ее надо, как мне кажется, с оформления комментариев. Уж больно убого сейчас они смотрятся.
Hello World!

"- Вылупился, - спокойно сказал Роман, глядя в потолок.
- Кто? - Мне было не по себе: крик был женский.
- Выбегаллов упырь, - сказал Роман. - Точнее, кадавр."
(с) А. и Б. Стругацкие

Итак, пришло время перейти от лабораторных изысканий к полевому тестированию. Тестировать мы будем разнообразные творения моего сомнительного гения, но начнем, собственно, с блогового движка AbendBlatt, создаваемого на базе фреймворка Django. О самом фреймворке, а вернее о моих впечатлениях от него мы поговорим позже, а пока я вкратце опишу что представляет из себя на данный момент AbendBlatt.
 
Итак, для начала несколько слов об архитектуре:
 
AbendBlatt это многопользовательский блог имеющий несколько уровней пользователей:
  • Администратор - пользовател обладающий абсолютно всеми правами. В данном случае это я.
  • Авторы - пользователи, имеющие возможность публиковать записи.
  • Читатели - могут читать все записи, комментировать их, участвовать в опросах ну и все такое прочее.
Записи блога подразделяются на Колонки aka Категории. Корме общих категорий, каждый Автор может вести собственную, Авторскую Колонку.
 
Единственное - на данный момент регистрация еще не работает. =)
 
Далее. Одна из особенностей блога это обработчики записей. Их есть два типа - PostPost и PreView.
PostPost-обработчики срабатывают при публикации записи. В первую очередь, они созданы для поддержки кросспостинга.
PreView-обработчики переваривают записи перед их выводом на экран. Конвертиры смайлов, контекстные анализаторы и так далее.
 
Блог снабжен системой тегов для сообщений. Она реализована благодаря приложению django-tagging.
 
Ну и все - что еще можно рассказать о системе в данный момент я не знаю, так что все остальное буду описывать в процессе. Вряд ли, конечно, кто-то в ближайшее время вообще найдет этот блог, но я пока и не очень хочу чтобы его активно находили, так что кросспостинг-обработчик (пока реализован только кросспостинг в LiveJournal) отключен. Сначала надо доделать интерфейсы регистрации, профиля пользователя и комментирования. После этого, думаю, кросспостинг уже можно будет включить, ну и ждать гостей.

Авторизация

Логин:

Пароль:


Регистрация | Забыли пароль?


Последние записи


Promo

Follow pyhoster on Twitter Subscribe

Реклама

A Django project.