<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <atom:link rel="self" type="application/rss+xml" href="http://breys.ru/rss"/>
    <language>ru</language>
    <copyright>Copyright 2008,2009 breys.ru</copyright>
    <title>Заметки на breys.ru</title>
    <link>http://breys.ru/blog/</link>
    <description>Заметки пользователя: Басманов, Брейс - дизайн студия</description>
    <item>
      <link>http://breys.ru/blog/1618.html</link>
      <guid>http://breys.ru/blog/1618.html</guid>
      <title>Flask restful сериализация sqlalchemy моделей в Json поток</title>
      <pubDate>Sun, 19 Apr 2015 16:25:06 +0400</pubDate>
      <description>&lt;p&gt;При использовать в проекте flask-restful удобно и необходимо возвращать в качестве результатов запросов объекты формируемые sqlalchemy моделями. Но есть одна проблема, так как очень часто эти модели содержат слишком много всяких дополнительных свойств, то встроенный сериализатор не справляется и ругается словами&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;is&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;not&lt;/span&gt;&lt;span&gt; JSON serializable&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Проблема решается путём переопределения встроенного сериализатора Flask, а делается это вот так:&lt;/p&gt;
&lt;p&gt;среди атрибутов приложения есть свойство указывающее на класс сериализатора Json, нам остаётся лишь взять базовый класс, переопределить его возможности обработкой своих типов и передать на исполнение в приложение (ниже общая схема)&lt;/p&gt;
&lt;pre&gt;&lt;p&gt;from flask.json import JSONEncoder&lt;/p&gt;class CustomJSONEncoder(JSONEncoder):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def default(self, obj):&lt;br /&gt;      # обработка собственных типов&lt;br /&gt;      if isinstance(obj, мои типы):&lt;br /&gt;         ....&lt;br /&gt;      # стандартная обработка&lt;br /&gt;      return JSONEncoder.default(self, obj)&lt;br /&gt;&lt;p&gt;app.json_encoder = CustomJSONEncoder
&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;Чтобы научить сериализатор обрабатывать объекты sqlalchemy необходимо использовать следующую конструкцию&lt;/p&gt;
&lt;pre&gt;&lt;p&gt;from sqlalchemy.ext.declarative import DeclarativeMeta&lt;/p&gt;class CustomJSONEncoder(JSONEncoder):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def default(self, obj):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if isinstance(obj.__class__, DeclarativeMeta):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # обрабатываем объект sqlalchemy&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fields = {}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; obj_dict = obj.__dict__&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for field in obj.__table__.columns.keys(): # получаем список полей связанной с моделью таблицы&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data = obj_dict.get(field) # извлекаем данные по имени поля&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; json.dumps(data)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fields[field] = data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; except TypeError:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fields[field] = None&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return fields&lt;/p&gt;&lt;p&gt;          return JSONEncoder.default(self, obj)&lt;/p&gt;&lt;/pre&gt;
&lt;p&gt;Собственно метод заключается в преобразование объекта sqlalchemy в обычный словарь, с последующей сериализацией полей словаря, имена которых являются полями таблицы, список которых получаем с помощью метода obj.__table__.columns.keys()&lt;/p&gt;
&lt;p&gt;&lt;a title="открыть: " rel="lightbox[roadtrip]" href="/upload/1429450216.04.png"&gt;&lt;img title="сериализация sqlalchemy моделей " src="/upload/images/1429450216.04.png" alt="сериализация sqlalchemy моделей " /&gt;&lt;/a&gt;&lt;a title="открыть: результат обращения к flask restful api" rel="lightbox[roadtrip]" href="/upload/1429450247.25.png"&gt;&lt;img src="/upload/images/1429450247.25.png" alt="результат обращения к flask restful api" /&gt;&lt;/a&gt;&lt;a title="открыть: пример кода restful кода" rel="lightbox[roadtrip]" href="/upload/1429450302.11.png"&gt;&lt;img src="/upload/images/1429450302.11.png" alt="пример кода restful кода" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Использование такого метода позволяет очень просто и наглядно формировать rest Api с помощью sqlalchemy моделей&lt;/p&gt;
&lt;pre&gt;return jsonify(result=True, id=id, page=model_Page.query.get(id))&lt;/pre&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/1617.html</link>
      <guid>http://breys.ru/blog/1617.html</guid>
      <title>Flask, создание собственных, расширенных виджетов форм для Flask.admin</title>
      <pubDate>Fri, 28 Nov 2014 08:36:19 +0400</pubDate>
      <description>&lt;p&gt;Часто требуется на формах Flask.admin создавать виджеты поведение которых не предусмотренно стандарными моделями и для решения этой проблемы необходимо уметь создавать свои виджеты, путём наследования базовых и расширением их функционала&lt;/p&gt;
&lt;p&gt;Например, мне в модели страницы необходимо указывать путь к шаблону с помощью которого будет генерироваться редактируемая страница, а список шаблонов получается путём сканирования директории шаблонов текущего домена (мультидоменная CMS), для решения этой проблемы наследую от&amp;nbsp; wtforms.fields.SelectField новый класс SelectTemplateField у которого переопределяю конструктор, где инициализирую параметр choices для родительского класса&lt;/p&gt;
&lt;p&gt;&lt;a title="открыть: Flask, wtforms.fields, SelectField" rel="lightbox[roadtrip]" href="/upload/1417153460.04.png"&gt;&lt;img src="/upload/images/1417153460.04.png" alt="Flask, wtforms.fields, SelectField" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;делается это вот так, в файле fields.py объявляю новый класс&lt;/p&gt;
&lt;pre&gt;class SelectTemplateField(SelectField):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self, *args, **kwargs):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; template_dir = os.path.join(kwargs[&amp;#039app_template&amp;#039], g.domen.template_path)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; choices = [ (name,name) for name in os.listdir(template_dir) if os.path.isfile(os.path.join(template_dir,name))]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; choices.sort()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; kwargs.pop(&amp;#039app_template&amp;#039)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; kwargs[&amp;#039choices&amp;#039] = choices&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return super(SelectTemplateField, self).__init__(*args, **kwargs)&lt;/pre&gt;
&lt;p&gt;в конструкторе&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;вычисляю путь к директории шаблонов текущего домена (template_dir)&lt;/li&gt;
&lt;li&gt;заполняю список именами файлов из этой директории&lt;/li&gt;
&lt;li&gt;сортирую список&lt;/li&gt;
&lt;li&gt;удаляю из kwargs элемент app_template, иначе базовый класс вылетит с ошибкой&lt;/li&gt;
&lt;li&gt;добавляю в отсортированный список с доступными шаблонами в kwargs&lt;/li&gt;
&lt;li&gt;вызываю конструктор базового класса&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Затем этот виджен нужно подключить к классу PageAdmin, делается это путём добавления в класс PageAdmin опции form_extra_fields сделующим образом:&lt;/p&gt;
&lt;pre&gt;form_extra_fields = {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#039template&amp;#039: SelectTemplateField(u&amp;#039шаблон&amp;#039,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; app_template = os.path.join(app.root_path, app.template_folder)),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;
&lt;p&gt;Здесь определяется стандартный класс для свойства template у класса Page, путём переопределения для него виджета с его инициализацией свойств label и app_template (которое затем используется в конструкторе переопредённого класса)&lt;/p&gt;
&lt;p&gt;Вот так легко и просто можно очень существенно расширить возможности генераторов форм во Flask&lt;/p&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/1616.html</link>
      <guid>http://breys.ru/blog/1616.html</guid>
      <title>Сброс пароля на Windows server 2012</title>
      <pubDate>Wed, 26 Nov 2014 08:27:02 +0400</pubDate>
      <description>&lt;p&gt;Так уж получается, что использовать Windows server приходится очень редко, по-этому постоянно памятую пароли. Опишу тут как сбрасывать пароли на Windows server 2012, но думаю этот способ подойдёт и для любой другой NT системы.&lt;/p&gt;
&lt;p&gt;Суть метода проста, нужно загрузиться с востановительного диска и заменить файл &lt;span style="color: #222222;"&gt;&lt;strong&gt; windows\system32\Utilman.exe &lt;/strong&gt;на&lt;strong&gt; cmd.exe&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #222222;"&gt;&lt;strong&gt;&lt;a title="открыть: Сброс пароля на Windows server 2012" rel="lightbox[roadtrip]" href="/upload/1416979699.74.png"&gt;&lt;img src="/upload/images/1416979699.74.png" alt="Сброс пароля на Windows server 2012" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #222222;"&gt;это необходимо для того чтобы при следующем запуске офтопика, в окне авторизации при нажатии кнопки Win+U запустила консоль, в которой уже можно по быстрому сменить с помощью команды&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #222222;"&gt;&lt;strong&gt;net user (имя пользователя) (пароль пользователя)&lt;br /&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/1615.html</link>
      <guid>http://breys.ru/blog/1615.html</guid>
      <title>Flask.admin FileAdmin проблема с локалями</title>
      <pubDate>Mon, 13 Oct 2014 09:38:35 +0400</pubDate>
      <description>&lt;p&gt;Если использовать FileAdmin модуля Flask.admin то в dev сервере есть небольшая проблема: файл, имеющие в именах кирилицу, при сохранении получаю имена без букв Кирилла и Мефодия, а в продакшен вообще появляются проблемы с обработкой строк, в том числе в файловом менеджере и логах. Проблема частично решается в продакшене частично решается путём установки переменной окружения при запуске uwsgi сервера через файл настроек&lt;/p&gt;
&lt;p&gt;допустим имеем такой стартовый скрипт&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;cat /etc/init/proj1.conf &lt;br /&gt;description "uWSGI server Proj#1"&lt;br /&gt;start on runlevel [2345]&lt;br /&gt;stop on runlevel [!2345]&lt;br /&gt;respawn&lt;br /&gt;exec /home/data/flask-project/env/bin/proj1_uwsgi.sh&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;который запускает&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;cat /home/data/flask-project/env/bin/proj1_uwsgi.sh&lt;br /&gt;#!/bin/sh&lt;br /&gt;/home/data/flask-project/env/bin/uwsgi -c /home/data/flask-project/proj1/uwsgi.ini&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;а уже в&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[uwsgi]&lt;br /&gt;socket = /tmp/proj1.sock&lt;br /&gt;master = true&lt;br /&gt;enable-threads = true&lt;br /&gt;processes = 3 &lt;br /&gt;chdir = /home/data/flask-project/proj1/&lt;br /&gt;module = app:app&lt;br /&gt;virtualenv = /home/data/flask-project/env/&lt;br /&gt;uid = ffsdmad&lt;br /&gt;gid = ffsdmad&lt;br /&gt;logto = /home/data/flask-project/proj1/error.log&lt;br /&gt;&lt;strong&gt;env = LC_ALL=ru_RU.UTF-8&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;устанавливается переменная env, которая используется для запуска app. Осталось решить проблему сохранения кирилических имён файлов&lt;/p&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/1613.html</link>
      <guid>http://breys.ru/blog/1613.html</guid>
      <title>Python: сортировка списков</title>
      <pubDate>Thu, 25 Sep 2014 11:00:30 +0400</pubDate>
      <description>&lt;p&gt;Предположим у вас есть список объектов с различными атрибутами, и вам необходимо отсортировать их этот список по нужному вам критерию, для этого вам необходимо воспользовать встроенной в списки функцией .sort с параметром key&lt;/p&gt;
&lt;p&gt;Например, у меня в базе есть список людей репрессированных за всякие нехорошие делишки, среди всех атрибутов этих людей меня интересуют пол и имена:&lt;/p&gt;
&lt;pre&gt;for a in rl:print a.id, a.sex, a.first_name&lt;br /&gt;... &lt;br /&gt;1551987 1 Виктория&lt;br /&gt;2212644 1 Клавдия&lt;br /&gt;2212647 1 Валентина&lt;br /&gt;2214814 2 Павел&lt;br /&gt;2223472 1 Владислава&lt;br /&gt;2223482 2 Павел&lt;br /&gt;2227653 1 Марина&lt;br /&gt;2227682 2 Николай&lt;br /&gt;2227757 2 Саша&lt;br /&gt;2227844 2 Николая&lt;br /&gt;2228553 2 Алекс&lt;br /&gt;2228608 1 Екатерина&lt;br /&gt;2228657 2 Максим&lt;br /&gt;2228692 2 Роман&lt;br /&gt;2228748 2 Василий-Дмитриевич&lt;br /&gt;2230327 2 Михаил&lt;br /&gt;2232569 2 Анатолий&lt;br /&gt;2232829 1 Анастасия&lt;br /&gt;2233073 2 Максим&lt;br /&gt;2233087 1 Инга&lt;br /&gt;2233098 2 Владимир&lt;br /&gt;2234717 2 Фёдор&lt;br /&gt;2235549 1 Марина&lt;br /&gt;2235552 2 Яросав&lt;br /&gt;2235850 2 Рустам&lt;br /&gt;2239743 2 Пётр&lt;br /&gt;2239766 1 Мария&lt;br /&gt;2239785 1 Юлия&lt;br /&gt;2240058 2 Николай&lt;br /&gt;2240658 2 Максим&lt;br /&gt;2240722 2 Евгений&lt;/pre&gt;
&lt;p&gt;Допусти мне нужно отсортировать список по полу, а затем по имени и для этого я использую следующий ключ&lt;/p&gt;
&lt;pre&gt;rl.sort(key = lambda x: x.sex)&lt;br /&gt;for a in rl:print a.id, a.sex, a.first_name&lt;br /&gt;...&lt;br /&gt;2232829 1 Анастасия&lt;br /&gt;2212647 1 Валентина&lt;br /&gt;1551987 1 Виктория&lt;br /&gt;2223472 1 Владислава&lt;br /&gt;2228608 1 Екатерина&lt;br /&gt;2233087 1 Инга&lt;br /&gt;2212644 1 Клавдия&lt;br /&gt;2227653 1 Марина&lt;br /&gt;2235549 1 Марина&lt;br /&gt;2239766 1 Мария&lt;br /&gt;2239785 1 Юлия&lt;br /&gt;2228553 2 Алекс&lt;br /&gt;2232569 2 Анатолий&lt;br /&gt;2228748 2 Василий-Дмитриевич&lt;br /&gt;2233098 2 Владимир&lt;br /&gt;2240722 2 Евгений&lt;br /&gt;2228657 2 Максим&lt;br /&gt;2233073 2 Максим&lt;br /&gt;2240658 2 Максим&lt;br /&gt;2230327 2 Михаил&lt;br /&gt;2227682 2 Николай&lt;br /&gt;2240058 2 Николай&lt;br /&gt;2227844 2 Николая&lt;br /&gt;2214814 2 Павел&lt;br /&gt;2223482 2 Павел&lt;br /&gt;2239743 2 Пётр&lt;br /&gt;2228692 2 Роман&lt;br /&gt;2235850 2 Рустам&lt;br /&gt;2227757 2 Саша&lt;br /&gt;2234717 2 Фёдор&lt;br /&gt;2235552 2 Яросав&lt;/pre&gt;
&lt;pre&gt;rl.sort(key = lambda x: x.first_name)&lt;br /&gt;for a in rl:print a.id, a.sex, a.first_name&lt;br /&gt;...&lt;br /&gt;2228553 2 Алекс&lt;br /&gt;2232829 1 Анастасия&lt;br /&gt;2232569 2 Анатолий&lt;br /&gt;2212647 1 Валентина&lt;br /&gt;2228748 2 Василий-Дмитриевич&lt;br /&gt;1551987 1 Виктория&lt;br /&gt;2233098 2 Владимир&lt;br /&gt;2223472 1 Владислава&lt;br /&gt;2240722 2 Евгений&lt;br /&gt;2228608 1 Екатерина&lt;br /&gt;2233087 1 Инга&lt;br /&gt;2212644 1 Клавдия&lt;br /&gt;2228657 2 Максим&lt;br /&gt;2233073 2 Максим&lt;br /&gt;2240658 2 Максим&lt;br /&gt;2227653 1 Марина&lt;br /&gt;2235549 1 Марина&lt;br /&gt;2239766 1 Мария&lt;br /&gt;2230327 2 Михаил&lt;br /&gt;2227682 2 Николай&lt;br /&gt;2240058 2 Николай&lt;br /&gt;2227844 2 Николая&lt;br /&gt;2214814 2 Павел&lt;br /&gt;2223482 2 Павел&lt;br /&gt;2239743 2 Пётр&lt;br /&gt;2228692 2 Роман&lt;br /&gt;2235850 2 Рустам&lt;br /&gt;2227757 2 Саша&lt;br /&gt;2234717 2 Фёдор&lt;br /&gt;2239785 1 Юлия&lt;br /&gt;2235552 2 Яросав&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;Думаю тут всё очевидно, но ещё интереснее когда нужна сортировка по нескольким полям, для этого расширяем ключ сортировки вот так:&lt;/p&gt;
&lt;pre&gt;rl.sort(key = lambda x: [x.sex,x.first_name.lower()])&lt;br /&gt;for a in rl:print a.id, a.sex, a.first_name&lt;br /&gt;... &lt;br /&gt;2232829 1 Анастасия&lt;br /&gt;2212647 1 Валентина&lt;br /&gt;1551987 1 Виктория&lt;br /&gt;2223472 1 Владислава&lt;br /&gt;2228608 1 Екатерина&lt;br /&gt;2233087 1 Инга&lt;br /&gt;2212644 1 Клавдия&lt;br /&gt;2227653 1 Марина&lt;br /&gt;2235549 1 Марина&lt;br /&gt;2239766 1 Мария&lt;br /&gt;2239785 1 Юлия&lt;br /&gt;2228553 2 Алекс&lt;br /&gt;2232569 2 Анатолий&lt;br /&gt;2228748 2 Василий-Дмитриевич&lt;br /&gt;2233098 2 Владимир&lt;br /&gt;2240722 2 Евгений&lt;br /&gt;2228657 2 Максим&lt;br /&gt;2233073 2 Максим&lt;br /&gt;2240658 2 Максим&lt;br /&gt;2230327 2 Михаил&lt;br /&gt;2227682 2 Николай&lt;br /&gt;2240058 2 Николай&lt;br /&gt;2227844 2 Николая&lt;br /&gt;2214814 2 Павел&lt;br /&gt;2223482 2 Павел&lt;br /&gt;2239743 2 Пётр&lt;br /&gt;2228692 2 Роман&lt;br /&gt;2235850 2 Рустам&lt;br /&gt;2227757 2 Саша&lt;br /&gt;2234717 2 Фёдор&lt;br /&gt;2235552 2 Яросав&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;Вот такой вот классный Python, здесь фишка в том, что функция sort получает функцию которая получает сравниваемый объект(x) и подготавливает его для сравнения, в последнем примере она формирует для сравнения список состоящий из поля объекта "пол"&amp;nbsp; и поля "имя" с применением функции перевода строки в нижний регистр (иначе возможны не корректные сортировки)&lt;/p&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/1612.html</link>
      <guid>http://breys.ru/blog/1612.html</guid>
      <title>Отключаем csrt проверку во Flask</title>
      <pubDate>Thu, 11 Sep 2014 13:41:15 +0400</pubDate>
      <description>&lt;p&gt;При отладке механизм защиты сайта csrt_token очень затрудняет жизнь, для его отключения, а лучше всего для управления этим механизмом нужно в config.py внести переменную&lt;/p&gt;
&lt;pre&gt;CSRF_ENABLED = True&lt;/pre&gt;
&lt;p&gt;Затем в __init__.py главного модуля добавить такие строки&lt;/p&gt;
&lt;pre&gt;if app.config[&amp;#039CSRF_ENABLED&amp;#039]:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; from flask_wtf.csrf import CsrfProtect&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CsrfProtect().init_app(app)&lt;/pre&gt;
&lt;p&gt;Затем при использовании форм передавать им дополнительный параметр&lt;/p&gt;
&lt;pre&gt;form = CreateProduct(csrf_enabled=app.config[&amp;#039CSRF_ENABLED&amp;#039])&lt;/pre&gt;
&lt;p&gt;Ну и на последок, в шаблонах, использовать вот такую конструкцию&lt;/p&gt;
&lt;pre&gt;{% if csrf_token %}{{ csrf_token() }}{% endif %}&lt;/pre&gt;
&lt;p&gt;таким образом изменяя состояние CSRF_ENABLED в конфиге вы будете контолировать этот параметр по всему проекту&lt;/p&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/1610.html</link>
      <guid>http://breys.ru/blog/1610.html</guid>
      <title>отключение журналов bind9</title>
      <pubDate>Tue, 12 Aug 2014 18:40:59 +0400</pubDate>
      <description>&lt;p&gt;Нет ничего удивительного в использовании на домашнем компьютере собственного DNS сервера, так это экономит траффик, ускоряет запросы к сайтам,&amp;nbsp; позволяет организовывать удобную домашную сеть с вайфаем и шарами, но весьма удивительно позволять&amp;nbsp; настроенному &lt;strong&gt;DNS&lt;/strong&gt; серверу писать свои сообщения в общесистемные журналы, потому что этот сервер весьма болтливый. Вот например анализ моего syslog, накопленный за 6 дней:&lt;/p&gt;
&lt;pre&gt;cat /var/log/syslog|sed &amp;#039s/\[/ /g&amp;#039|awk &amp;#039{print $5}&amp;#039|sort| uniq -c|sort -n&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1 avahi-daemon&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4 dbus&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7 rsyslogd:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 14 acpid:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 14 NetworkManager&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 15 anacron&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 15 pppd&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 31 CRON&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 48 dhcpd:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 679 kernel:&lt;br /&gt;&amp;nbsp;&amp;nbsp; 1982 named&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;тут сразу видно, что каждые два из трёх сообщения произносится &lt;strong&gt;DNS сервером&lt;/strong&gt;. Думаю на домашнем сервере можно просто напросто отключить логирование &lt;strong&gt;DNS&lt;/strong&gt;, ну или перенаправить в отдельные файлы&lt;/p&gt;
&lt;p&gt;Для отключения журналирования события &lt;strong&gt;BIND9&lt;/strong&gt; достаточно добавит опцию&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;querylog false;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;в раздел &lt;strong&gt;options&lt;/strong&gt; файла &lt;strong&gt;/etc/bind/named.conf.options&lt;/strong&gt;&lt;/p&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/1609.html</link>
      <guid>http://breys.ru/blog/1609.html</guid>
      <title>python ProxyError</title>
      <pubDate>Mon, 04 Aug 2014 12:14:12 +0400</pubDate>
      <description>&lt;p&gt;Если ваш скрипт, работающий с https, вдруг начал выдавать вот такую ошибку&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;requests.exceptions.ProxyError: Cannot connect to proxy. Socket error: Tunnel connection failed: 302 Moved Temporarily.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;то скорее всего вы используете прокси для браузера, чтобы отучить скрипт использовать proxy достаточно перед запуском скрипта сбросить значение переменной окружения https_proxy любым из доступных способов, например вот так&lt;/p&gt;
&lt;pre&gt;unset https_proxy&lt;br /&gt;python tests.py&lt;/pre&gt;
&lt;p&gt;или запускать скрипт вот так&lt;/p&gt;
&lt;pre&gt;https_proxy=&amp;#039&amp;#039 ./tests.py&lt;/pre&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/1608.html</link>
      <guid>http://breys.ru/blog/1608.html</guid>
      <title>Sqlite3 работа с несколькими базами</title>
      <pubDate>Mon, 21 Jul 2014 15:12:29 +0400</pubDate>
      <description>&lt;p&gt;Когда необходимо поработать сразу с несколькими базами SQLite, используя их в одном запросе, то приходится пошаманить и найти не самые хорошо задокументированные функции консольного клиента&lt;/p&gt;
&lt;p&gt;Допустим вы работаете с текущей сессии с base.db и подключили её вот так:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;$ &lt;strong&gt;sqlite3 base.db&lt;/strong&gt;&lt;br /&gt;SQLite version 3.8.2 2013-12-06 14:53:30&lt;br /&gt;Enter ".help" for instructions&lt;br /&gt;Enter SQL statements terminated with a ";"&lt;br /&gt;sqlite&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;проверяем подключенные базы и видим&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;sqlite&amp;gt; &lt;strong&gt;.database&lt;/strong&gt;&lt;br /&gt;seq&amp;nbsp; name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; file&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;---&amp;nbsp; ---------------&amp;nbsp; ----------------------------------------------------------&lt;br /&gt;0&amp;nbsp;&amp;nbsp;&amp;nbsp; main&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /home/ffsdmad/Flask/base.db&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;подключем ещё одну и проверяем&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;sqlite&amp;gt; &lt;strong&gt;attach database &amp;#039base.dbbase.db&amp;#039 as b2;&lt;/strong&gt;&lt;br /&gt;sqlite&amp;gt; &lt;strong&gt;.database&lt;/strong&gt;&lt;br /&gt;seq&amp;nbsp; name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; file&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;---&amp;nbsp; ---------------&amp;nbsp; ----------------------------------------------------------&lt;br /&gt;0&amp;nbsp;&amp;nbsp;&amp;nbsp; main&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /home/ffsdmad/Flask/base.db&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;2&amp;nbsp;&amp;nbsp;&amp;nbsp; b2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /home/ffsdmad/Flask/base.dbbase.db&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;br /&gt;sqlite&amp;gt;&lt;strong&gt; select id, date from b2.pages;&lt;/strong&gt;&lt;br /&gt;1|2014-03-27&lt;br /&gt;2|2014-03-27&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;вот так, теперь легко можно стряпать вставки из другой базы используя алиас&lt;/p&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/1607.html</link>
      <guid>http://breys.ru/blog/1607.html</guid>
      <title>Как украли яндекс.деньги, кто виноват</title>
      <pubDate>Sun, 20 Jul 2014 15:18:50 +0400</pubDate>
      <description>&lt;p&gt;Сегодня обнаружил, что с моего яндекс кошелька спёрли деньги при следующих обстоятельствах:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;спёрли 1,900р., совсем маленькая шабашка, но это первый раз когда у меня, как у линуксоида, спёрли электронные деньги, причём в системе к которой раньше было большое доверие&lt;/li&gt;
&lt;li&gt;в &lt;a href="https://money.yandex.ru/sessions.xml"&gt;истории платежей&lt;/a&gt; указанно, что платёж произошёл ночью, 20.07.2014 02:58 с IP адреса &lt;a href="https://www.nic.ru/whois/?query=46.36.221.5"&gt;46.36.221.5&lt;/a&gt; на счёт яндекс счёт 410011814039493&lt;/li&gt;
&lt;li&gt;в деталях платежа указано следующее: 24obmin.com: обмен №758 1939.98 Яндекс.Деньги на 610.63 &lt;strong&gt;Приват24 UAH &lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;мой аккаунт в яндексе авторизован с помощью паспорта в евросети&lt;/li&gt;
&lt;li&gt;IP адрес 46.36.221.5 принадлежит &lt;a href="http://fastvps.ru/"&gt;fastvps.ru&lt;/a&gt;, который занимается предоставлением аренды хостинга&lt;/li&gt;
&lt;li&gt;пароль ни кто кроме бывшей жены не знал&lt;/li&gt;
&lt;li&gt;ящиком не пользовался уже много лет&lt;/li&gt;
&lt;li&gt;воришки сменили мой пароль yandex аккаунта и платёжный пароль, для их восставления мне пришлось получать уведомления по SMS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;а истории посещений моего аккаунта видно, что начиная с середины декабря прошлого года происходит иностранная активность, в частность вот лог первого вход с подозрительно чужого аккаута&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;37.115.158.10 входил [2013-12-15, / 00:31,] address: Degtyarevskaya, 53 address: Kiev, Ukraine descr: Kyivstar GSM descr: Kyivstar GSM, Kiev, Ukraine descr: Ukrainian mobile phone operator&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;а затем регулярные входы из различных стран&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;117.203.241.62 входил [2013-12-22, / 14:55,] address: 2nd Floor, Telephone Exchange, Sector 62 address: 8th Floor,148-B Statesman House address: Barakhamba Road, New Delhi - 110 001 address: Bharat Sanchar Nigam Limited address: Broadband Networks address: BSNL NOC Bangalore address: Internet Cell address: Noida descr: Broadband Multiplay Project, O/o DGM BB, NOC BSNL Bangalore descr: BSNL Internet&lt;/p&gt;
&lt;p&gt;82.146.43.62 входил [2014-01-15, / 21:28,] address: CJSC The First, Raduzhny 34a address: Irkutsk, 664017, Russian Federation address: PoBox64, Irkutsk, 664017 address: Raduzhny st. 34a address: Russian Federation descr: TheFirst-RU descr: TheFirst-RU clients (WebDC Msk)&lt;br /&gt;&lt;br /&gt;193.0.147.50 входил [2014-02-23, / 23:12,] address: Khimki, Moscow region, Russia address: Yubileyny av., 59-11 descr: Freestyle Ltd. descr: route object&lt;br /&gt;&lt;br /&gt;212.86.254.138 входил [2014-03-20, / 15:13,] address: 30V Fizkultury Str. address: Farlep Invest PrJSC address: Kiev, 03680, Ukraine address: PJSC FARLEP-INVEST 30V Fizkultury St. 03680 Kiev Ukraine descr: ALKAR descr: PRIVATE JOINT-STOCK COMPANY FARLEP-INVEST&lt;br /&gt;&lt;br /&gt;37.212.185.156 входил [2014-04-18, / 10:00,] address: 1, Kharkovskaya str., address: 220073, Minsk address: Minsk Public Telephone Network address: Republican Unitary Enterprise BELTELECOM Olga Romaniuk 6, Engels street 220030 Minsk BELARUS address: The Republic of Belarus descr: BELPAK-2012-3 descr: Republican Unitary Telecommunication Enterprise Beltelecom&lt;br /&gt;&lt;br /&gt;190.37.87.220 входил [2014-05-04, / 14:37,] address: 1060 - Caracas - MI address: Segunda Avenida de los Palos Grandes, 000, Entre Av. Fr address: Segunda Avenida de los Palos Grandes, Entre Av. Fr, 000,&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;выходит что в конце декабря 2013 года, кто-то в революционном киеве сумел подобрать мой пароль, а затем ждал когда же в кошельке появятся деньги (я им не пользовался лет шесть), а когда деньги там появились, то они были переведены на яндекс кошелёк 410011814039493 с помощью виртуально машины размещённой у fastvps.ru&lt;/p&gt;
&lt;p&gt;Пока что я написал в абузу fastvps.ru и саппорт Яндекса&lt;/p&gt;
&lt;p&gt;Ну и как то автоматом встаёт вопрос о надёжности Яндекса как такового, потому что совершенно не ясно каким образом воришки сменили мои пароли если смена пароля происходит через SMS уведомления, а я таких не получал, ну и ещё, почему яндекс не сообщил мне, что в мой яндекс кошелёк регулярно заходят из разных стран.&lt;/p&gt;
&lt;p&gt;В общем Яндексом пользоваться пока что не буду.&lt;/p&gt;
&lt;p&gt;ps: скрипт для декодирования истории яндекса:&lt;/p&gt;
&lt;pre&gt;#!/bin/bash&lt;br /&gt;function date_time_ip2whois {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; echo "*-*-*-*-*-*-*-*-*-*-"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; echo "$3 входил [$1 / $2]"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; whois $3 | egrep -i &amp;#039^descr:|^Address:&amp;#039 |sort| uniq&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; echo "---"&lt;br /&gt;}&lt;br /&gt;date_time_ip2whois $1, $2, $3 | xargs&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;Применять вот так:&lt;/p&gt;
&lt;pre&gt;egrep -v 192.168.[0-9]+|172.19.145.[0-9]+&amp;#039 session_yandex.txt |awk &amp;#039{print "bin/whois_session.sh", $0}&amp;#039 |sh 2&amp;gt; /dev/null&amp;nbsp; |egrep -v &amp;#039Kirov|MefaFon&amp;#039 &amp;gt; session_yandex_decode.txt&lt;/pre&gt;
&lt;p&gt;&lt;img title="Tongue out" src="/tinymce/jscripts/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif" border="0" alt="Tongue out" /&gt;&lt;/p&gt;</description>
      <author>ffsdmad@jabber.ru ( Басманов ) </author>
    </item>
  </channel>
</rss>

