<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2russianfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.cyxapeff.org/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Cyxapeff Blog</title><link>http://cyxapeff.org/blog/</link><description>Блог.</description><language>ru-RU</language><lastBuildDate>Fri, 12 Mar 2010 12:24:21 -0000</lastBuildDate><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.cyxapeff.org/CyxapeffBlog" /><feedburner:info uri="cyxapeffblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.cyxapeff.org%2FCyxapeffBlog" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.cyxapeff.org%2FCyxapeffBlog" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.cyxapeff.org%2FCyxapeffBlog" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.cyxapeff.org/CyxapeffBlog" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.cyxapeff.org%2FCyxapeffBlog" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.cyxapeff.org%2FCyxapeffBlog" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.cyxapeff.org%2FCyxapeffBlog" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://lenta.yandex.ru/settings.xml?name=feed&amp;url=http%3A%2F%2Ffeeds.cyxapeff.org%2FCyxapeffBlog" src="http://lenta.yandex.ru/i/addfeed.gif">?????? ? ??????.?????</feedburner:feedFlare><item><title>Фенечки</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/qk9tgYQnKf4/</link><description>
&lt;p&gt;За последнее время накопилось несколько полезных фенечек, которые могут кому-то пригодиться. О них я уже упоминал в своём &lt;a href="http://twitter.com/cyxapeff"&gt;твиттере&lt;/a&gt;, но подумал, что продублировать в блоге не помешает.
&lt;/p&gt;

&lt;h3&gt;Google Translate plugin for vimperator&lt;/h3&gt;
&lt;p&gt;Давно уже пользуюсь &lt;a href="http://vimperator.org/vimperator"&gt;vimperator&lt;/a&gt;'ом, а так же часто нужно перевести слово или фразу. Есть куча способов сделать это, но я уже настолько привык к вимператору, что команда мне кажется самым простым способом.
&lt;/p&gt;
&lt;p&gt;Использование:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:tr[anslate] [-l[angpair] from|to] word or phrase
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Забрать последнюю версию можно с Launchpad: &lt;a href="https://code.launchpad.net/~cyxapeff/+junk/vimperator-translate"&gt;https://code.launchpad.net/~cyxapeff/+junk/vimperator-translate&lt;/a&gt;
&lt;/p&gt;

&lt;h3&gt;Tr.im plugin for vimperator&lt;/h3&gt;
&lt;p&gt;Нашёл отличный &lt;a href="http://code.google.com/p/vimperator-labs/issues/detail?id=55"&gt;плагин&lt;/a&gt; который сокращает ссылки используя мой любимый &lt;a href="http://tr.im"&gt;tr.im&lt;/a&gt;. Но используя я его обычно для уже открытой страницы, чтобы поделиться ссылкой в твиттере или джаббере, а он не умеет самостоятельно подставлять URL текущей страницы. Пришлось научить.
&lt;/p&gt;
&lt;p&gt;Исходный код плагина:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;commands.addUserCommand ("trim",
    "Tr.im a url and copy it to the clipboard",
    function (args)
    {
        if (args[0] &amp;amp;&amp;amp; args[0] != '' ) { url = args[0]; }
        else { url = buffer.URL; }
        util.httpGet ("http://tr.im/api/trim_simple?url=" +encodeURIComponent (url), function (req)
             {
             if (req.status == 200)
             {
             util.copyToClipboard (req.responseText);
             liberator.echo ("Trim URL: " +req.responseText);}
             else
             liberator.echoerr("Error contacting tr.im!\n");
             }
        );
    });
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как видно если вызвать :trim без параметров - подставится текущий URL.
&lt;/p&gt;

&lt;h3&gt;Twibirthday&lt;/h3&gt;
&lt;p&gt;Очередной &lt;a href="http://twitter.com/twibirthday"&gt;бот&lt;/a&gt; для твиттера. Занимается тем, чем сообщает когда вы зарегистрировались и за день до тви-рождения напоминает об этом личным сообщением. Для использования нужно просто его зафолловить @&lt;a href="http://twitter.com/twibirthday"&gt;twibirthday&lt;/a&gt;.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2010/02/25/fenechki/</guid><feedburner:origLink>http://cyxapeff.org/blog/2010/02/25/fenechki/</feedburner:origLink></item><item><title>Rss с drive2</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/DsNW5K4TdJU/</link><description>
&lt;p&gt;Мне очень нравится сайт &lt;a href="http://drive2.ru"&gt;drive2.ru&lt;/a&gt;. Отличное сообщество, красивые машины и интересные обсуждения. Но разработчики сайта не позаботились о том, чтобы отдавать ленту событий в RSS. Пришлось снова писать костыли. На этот раз костыль я решил написать не на привычном и горячо любимом питоне, а на руби.
&lt;/p&gt;
&lt;p&gt;Распарсить ленту не представляет труда, а вот авторизоваться на сайте с ходу не получится. На форму входа навешен javascript и без него "войти" невозможно. Мне известны два способа как решить эту проблему. Во-первых, использовать какую-нибудь библиотеку, которая работает с настоящим браузером. Соответственно и javascript и всё остальное там прекрасно работает. Для руби есть, например, &lt;a href="http://watir.com"&gt;Watir&lt;/a&gt;. Во-вторых, можно своему скрипту подсунуть рабочие куки и таким образом вообще пропустить стадию авторизации. Собственно этот второй путь я и выбрал.
&lt;/p&gt;
&lt;p&gt;Моим повседневным браузером является firefox, который хранит куки в базе данных SQLite, которая лежит в ~/.mozilla/firefox/%profile%/cookies.sqlite (путь для линукса, в windows очень похожий). Откроем этот файл и посмотрим что там внутри:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ sqlite3 /tmp/cookies.sqlite
SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite&amp;gt; .tables
moz_cookies
sqlite&amp;gt; .headers on
sqlite&amp;gt; select * from moz_cookies limit 3;
id|name|value|host|path|expiry|lastAccessed|isSecure|isHttpOnly
1254769091658566|PREF|моя кука|.google.com|/|1326648773|1264938324355994|0|0
1254769091658706|NID|моя кука|.google.com|/|1280320725|1264938264007374|0|1
1254769091832306|PREF|моя кука|.google.ru|/|1317842867|1264938309932153|0|0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Отлично. Значит мы без труда может вытащить рабочие куки из нашего браузера. Но браузер работает на десктопе, а скрипт должен работать на сервере, чтобы постоянно мониторить обновления ленты. Следовательно нужно каким-то образом держать на сервере актуальную базу. Я для этого решил использовать Dropbox, т.к он и так постоянно запущен как на сервере, так и на десктопе. Кидаю ссылку в директорию дропбокса и готово.
&lt;/p&gt;
&lt;p&gt;Ну а теперь собственно сам скрипт.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# coding: utf-8

require 'sqlite3'
require 'net/http'
require 'nokogiri'
require 'rss/maker'

class Parser
    TITLE = "Drive2.ru Feed"
    LINK = "http://www.drive2.ru/my/feed"
    DESCRIPTION = "Rss from my feed"
    def initialize(sqlfile = nil, txtfile = nil)
        if sqlfile
            @doc = Nokogiri::HTML(get_page(sqlfile))
        elsif txtfile
            @doc = Nokogiri::HTML(get_from_file(txtfile))
        else
            exit()
        end
    end

    def get_page(sqlfile)
        cookies = ''
        `cp #{sqlfile} /tmp/cookies.sqlite`
        db = SQLite3::Database.new('/tmp/cookies.sqlite')
        db.execute( "select name, value from moz_cookies where host = '.www.drive2.ru'" ) do |row|
             cookies += row[0] + '=' + row[1] + ';'
        end

        con = Net::HTTP.new('www.drive2.ru', 80)
        path = '/my/feed/'
        headers = { 'Cookie' =&amp;gt; cookies,
                    'Refer' =&amp;gt; 'http://www.drive2.ru',
                    'User-Agent' =&amp;gt; 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.7) Gecko/20100105 Shiretoko/3.5.7'}
        res = con.get(path, headers)

        res.body
    end

    def get_from_file(txtfile)
        f = File.new(txtfile)
        f.read()
    end

    def login?
        title = @doc.css('title').first.content.strip
        return true if title == 'Лента'
        return false
    end

    def parse
        result = Array.new
        @doc.css('.journalentries').each do |entry|
            time = entry.css('.eventtime').first.content
            time = Time.parse(modify_time(time))
            title = entry.css('h3').first.content
            content = entry.css('div:regex("j\d+")', Class.new {
                def regex node, regex
                    node.find_all { |node| node['id'] =~ /#{regex}/ }
                end
            }.new).first.inner_html
            link = entry.css('.commentslink &amp;gt; a').first['href']
            result &amp;lt;&amp;lt; { :title =&amp;gt; title,
                        :datetime =&amp;gt; time,
                        :content =&amp;gt; content,
                        :link =&amp;gt; 'http://www.drive2.ru' + link}
        end
        return result
    end

    def create_rss(entries)
        content = RSS::Maker.make('2.0') do |m|
            m.channel.title = TITLE
            m.channel.link = LINK
            m.channel.description = DESCRIPTION
            m.items.do_sort = true # sort items by date

            entries.each do |entry|
                i = m.items.new_item
                i.title = entry[:title]
                i.link = entry[:link]
                i.date = entry[:datetime]
                i.description = entry[:content]
            end
        end
        return content
    end

private
    def modify_time(string)
        dict = { 'января в' =&amp;gt; 'Jan', 'февраля в' =&amp;gt; 'Feb',
                 'марта в' =&amp;gt; 'Mar', 'апреля в' =&amp;gt; 'Apr',
                 'мая в' =&amp;gt; 'May', 'июня в' =&amp;gt; 'Jun',
                 'июля в' =&amp;gt; 'Jul', 'августа в' =&amp;gt; 'Aug',
                 'сентября в' =&amp;gt; 'Sep', 'октября в' =&amp;gt; 'Oct',
                 'ноября в' =&amp;gt; 'Nov', 'декабря в' =&amp;gt; 'Dec',
                 'вчера в' =&amp;gt; (Time.now - 60*60*24).strftime("%d %b")}
        dict.each do |key, value|
            string.sub!(key, value)
        end
        return string
    end
end

if __FILE__ == $0
    parser = Parser.new('/home/smacker/Dropbox/cookies.sqlite')
    if parser.login?
        rss = parser.create_rss(parser.parse)
        f = File.open('/var/www/media/drive2.rss', 'w')
        f.write(rss)
        f.close()
     end
end
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Если код не очень красив, не сердчайте, я только начал изучать ruby. В методе get_page я копирую базу в /tmp, потому что пока firefox запущен, он блокирует базу и не даёт из неё ничего читать. Готовый rss файл просто кладётся в директорию доступную по http, а эту ссылку я добавляю в свой Google Reader. Ну а скрипт соответственно прописан в кроне и выполняется раз в 2 часа. Надеюсь, он пригодится кому-нибудь ещё.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2010/01/31/rss-s-drive2/</guid><feedburner:origLink>http://cyxapeff.org/blog/2010/01/31/rss-s-drive2/</feedburner:origLink></item><item><title>Небольшое обновление блога</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/y_jPG1pgxOU/</link><description>
&lt;p&gt;Уже довольно давно пушнул новую ревизию блога. Что появилось нового:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Поиск реализованный через Google Custom Search. Сейчас стало модно всё переносить на клиента, в том числе и поиск, но у меня сделано по-старенькому. Запросы к гуглу генерирует сервер, ответы разбирает он же. Ну и выдаёт уже готовый html.
 &lt;/li&gt;

 &lt;li&gt;
     Поддержка gravatar. Здесь всё и так понятно. У комментариев появились аватарки.
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Обновление маленькое, зато исправлено множество багов.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2010/01/22/nebolshoe-obnovlenie-bloga/</guid><feedburner:origLink>http://cyxapeff.org/blog/2010/01/22/nebolshoe-obnovlenie-bloga/</feedburner:origLink></item><item><title>Инстументальные среды разработки для Python</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/NKNM2ZG9dYg/</link><description>
&lt;p&gt;Этот пост в первую очередь предназначается для сайта welinux.ru, но продублировать его в блоге, думаю, будет не лишнем&lt;/p&gt;

&lt;p&gt;Писать, как известно, можно где угодно и как угодно. Вплоть до скриптов на листке бумаги, а интерпретатор держать в голове. Всё зависит от личных предпочтений того или иного человека. Я расскажу о тех средах в которых хоть немного успел поработать. И начну с самого просто:&lt;/p&gt;

&lt;h2&gt;gedit&lt;/h2&gt;
&lt;p&gt;&lt;a id="qw.n" href="http://docs.google.com/a/smacker.ru/File?id=dhspk665_165kqtcdjfj_b" target="_blank"&gt;&lt;img style="width: 320px; height: 226.367px; float: right; margin-left: 1em; margin-right: 0pt;" src="http://docs.google.com/a/smacker.ru/File?id=dhspk665_165kqtcdjfj_b"&gt;&lt;/a&gt;Стандартный текстовый редактор из gnome. Не смотря на то, что большинство считает его чем-то вроде виндового блокнота именно в этом редакторе я провёл большую часть времени программирую на питоне. А случилось это не потому, что я такой мазохист, а потому что в своё время наткнулся на &lt;a title="список плагинов" href="http://live.gnome.org/Gedit/Plugins" id="uuw_"&gt;список плагинов&lt;/a&gt;, которые реализовали всё что мне было необходимо.
&lt;/p&gt;&lt;p&gt;
Из коробки уже доступны интересные плагины &lt;b&gt;File Browser&lt;/b&gt;, &lt;b&gt;Python console&lt;/b&gt; назначение которых понятны из названия. А так же мега полезный &lt;b&gt;Snippets. &lt;/b&gt;Что такое сниппеты, наверно, тоже уже большинству понятно, для остальных - это небольшие кусочки кода, которые заменяют определённые нами слова. Гораздо понятней и наглядней будет не рассказывать, а &lt;a title="посмотреть видео" href="http://vimeo.com/3350617" id="g0br"&gt;посмотреть видео&lt;/a&gt;. По-мимо этого я использовал один из плагинов реализующих &lt;b&gt;Autocomplete&lt;/b&gt;, продвинутый &lt;b&gt;поиск&lt;/b&gt;, &lt;b&gt;Lorem Ipsum&lt;/b&gt;, один из &lt;b&gt;ToDo&lt;/b&gt; плагинов. На тот момент они с лихвой покрывали все мои потребности.
&lt;/p&gt;&lt;p&gt;
Так же есть возможность использовать и &lt;a title="цветовые схемы" href="http://live.gnome.org/GtkSourceView/StyleSchemes" id="ozsr"&gt;цветовые схемы&lt;/a&gt;. Я использовал &lt;b&gt;Desert&lt;/b&gt;, который в будущем ставил везде куда только можно прикрутить свою раскаску.&lt;/p&gt;

&lt;h2 style="clear:right;"&gt;Vim&lt;/h2&gt;
&lt;p&gt;&lt;a id="ldfs" href="http://docs.google.com/a/smacker.ru/File?id=dhspk665_164fbq4cxgt_b" target="_blank"&gt;&lt;img style="width: 320px; height: 189.342px; float: right; margin-left: 1em; margin-right: 0pt;" src="http://docs.google.com/a/smacker.ru/File?id=dhspk665_164fbq4cxgt_b"&gt;&lt;/a&gt;На данный момент использую именно этот редактор. Сам по себе редактор очень мощный, а от многообразия плагинов просто захватывает дух. Как точить его до мини IDE отлично рассказано в гугле. Ну, например,&amp;nbsp; &lt;a title="раз статьи" href="http://allaboutvim.blogspot.com/2007/12/vim-python.html" id="ah-a"&gt;раз статьи&lt;/a&gt; и &lt;a title="два статья" href="http://habrahabr.ru/blogs/python/74128/" id="ewar"&gt;два статья&lt;/a&gt;. Основные моменты там отметили, а дальше уже опять же дело вкуса.&lt;/p&gt;

&lt;h2 style="clear:right;"&gt;SciTE&lt;/h2&gt;
&lt;p&gt;
Это совсем не IDE, а просто хороший текстовый редактор основанный на Scintilla. Для создания небольших скриптов и чтения исходников подходит отлично. &lt;a title="Сайт программы" href="http://www.scintilla.org/SciTE.html" id="f7ur"&gt;Сайт программы&lt;/a&gt;.&lt;/p&gt;

&lt;h2 style="clear:right;"&gt;Eric&lt;/h2&gt;
&lt;p&gt;&lt;a id="wqiu" href="http://docs.google.com/a/smacker.ru/File?id=dhspk665_166cxxspqcq_b" target="_blank"&gt;&lt;img style="width: 320px; height: 232.661px; float: right; margin-left: 1em; margin-right: 0pt;" src="http://docs.google.com/a/smacker.ru/File?id=dhspk665_166cxxspqcq_b"&gt;&lt;/a&gt;А вот уже пошли настоящие IDE. И &lt;a title="Eric4" href="http://eric-ide.python-projects.org/" id="nok:"&gt;Eric4&lt;/a&gt; это одна из немногих IDE ориентированных именно на Python. Сама же она так же написана на питоне, а в качестве gui toolkit используется qt4. В качестве текстового редактора используется Scintilla. Тесно познакомится с этой средой разработки мне помешала моя преданность gtk, т.к в любом qt приложении я чувствую себя неуютно. Так же моё знакомство происходило уже довольно давно (вестимо пару лет назад), но и на тот момент Eric был очень богат на разнообразные фичи. Их список можно увидеть на &lt;a title="сайте разработчика" href="http://eric-ide.python-projects.org/" id="jz9s"&gt;сайте редактора&lt;/a&gt;. Что не понравилось - это перегруженность интерфейса. Этот минус можно приписать всем IDE что я буду рассматривать дальше. И именно из-за него я использую vim.&lt;/p&gt;

&lt;h2 style="clear:right;"&gt;Eclipse + PyDev&lt;/h2&gt;
&lt;p&gt;&lt;a id="eq5x" href="http://docs.google.com/a/smacker.ru/File?id=dhspk665_167g9bhhhhs_b" target="_blank"&gt;&lt;img style="width: 320px; height: 225.185px; float: right; margin-left: 1em; margin-right: 0pt;" src="http://docs.google.com/a/smacker.ru/File?id=dhspk665_167g9bhhhhs_b"&gt;&lt;/a&gt;Одна из самых популярных IDE отлично работает с питоном благодаря плагину &lt;a title="PyDev" href="http://pydev.org/index.html" id="jrhk"&gt;PyDev&lt;/a&gt;, в который не так давно влился и ранее закрытый платный PyDev Extension. Среда разработки конечно очень тяжёлая, но работать в ней действительно удобно. Если заниматься программирование на питоне профессионально, то это эклипс, на мой взгляд, один из лучших продуктов. Для меня же, когда питон является по большей части хобби - возможности среды избыточны.&lt;/p&gt;

&lt;h2 style="clear:right;"&gt;NetBeans&lt;/h2&gt;
&lt;p&gt;&lt;a id="nci6" href="http://docs.google.com/a/smacker.ru/File?id=dhspk665_168d782fkc2_b" target="_blank"&gt;&lt;img style="width: 320px; height: 200px; float: right; margin-left: 1em; margin-right: 0pt;" src="http://docs.google.com/a/smacker.ru/File?id=dhspk665_168d782fkc2_b"&gt;&lt;/a&gt;Не менее мощная среда разработки &lt;a title="NetBeans" href="http://wiki.netbeans.org/Python" id="x36y"&gt;NetBeans&lt;/a&gt; так же отлично работает с питоном с недавнего времени. Моё знакомство с этой средой было очень недолгим, поэтому предлагаю заинтересовавшимся самим опробовать IDE.&lt;/p&gt;

&lt;p&gt;Конечно этим не ограничивается список редакторов в которых можно и нужно писать на питоне. Например, в далёком прошлом пользуясь windows я любил &lt;b&gt;&lt;a title="jEdit" href="http://www.jedit.org" id="tm44"&gt;jEdit&lt;/a&gt;&lt;/b&gt;, написанный на Java. Под линуксом же с ним были небольшие проблемы и я быстро нашёл замену.&amp;nbsp; Или &lt;b&gt;&lt;a title="Geany" href="http://www.geany.org" id="s_am"&gt;Geany&lt;/a&gt;&lt;/b&gt; очень лёгкая IDE, которая не подошла мне в силу причин которые я уже не помню. Есть ещё одна довольно интересная лёгкая среда разработки &lt;b&gt;&lt;a title="PIDA" href="http://pida.co.uk/" id="s9u."&gt;PIDA&lt;/a&gt;&lt;/b&gt;, а интересна она тем, что в качестве текстового редактора использует vim. А список тех редакторов которые я не попробовал можно продолжать очень долго Kate, KDevelop, Emacs, Anjuta, IntelliJ IDEA и т.д. Если у вас до сих пор нет любимой среды разработки - попробуйте! И я уверен, вы найдёте милый вашему сердцу редактор.&lt;/p&gt;

&lt;p&gt;&lt;span style="color: rgb(204, 204, 204);"&gt;* Все скриншоты взяты на просторах интернета&lt;/span&gt;&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2009/12/03/instumentalnyie-sredyi-razrabotki-dlya-python/</guid><feedburner:origLink>http://cyxapeff.org/blog/2009/12/03/instumentalnyie-sredyi-razrabotki-dlya-python/</feedburner:origLink></item><item><title>Gajim и ссылки в xhtml</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/ti2isz-mZeU/</link><description>
&lt;p&gt;Довольно активно использую транспорт из твиттера tweet.im, а моим любимым jabber клиентом является gajim. И всё бы хорошо, но tweet.im возвращая xhtml не делает ссылки внутри твита ссылками, поручая это клиенту. Гаджим же программа умная и создаёт ссылки только в plain тексте, в xhtml же никаких преобразований не делает, что вполне логично. Если уж приходит xhtml, то там уже и так всё размечено должно быть, а что не размечено - видимо так и задумывалось. Ну и в результате я получал ссылки на которые нельзя тыкнуть. Когда надоело копировать адреса в браузер, пришлось немного хакнуть gajim. Этим патчиком и делюсь: &lt;a href="http://cyxapeff.org/media/gajim0.12.1_url_twitter.patch"&gt;для gajim 0.12.1&lt;/a&gt; (в Ubuntu Jaunty как раз он) и для последней стабильной версии &lt;a href="http://cyxapeff.org/media/gajim0.12.5_url_twitter.patch"&gt;для gajim 0.12.5&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Использовать примерно так:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo mv gajim0.12.1_url_twitter.patch /usr/share/gajim/src/
cd /usr/share/gajim/src/
sudo patch -i gajim0.12.1_url_twitter.patch
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;После рестарта гаджима - ссылки наконец-то станут ссылками.
&lt;/p&gt;
&lt;p&gt;Вот так оно выглядит у меня:
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://cyxapeff.org/media/blog/img/screenshot_gajim.png" alt="&amp;quot;Gajim&amp;quot;"/&gt;
&lt;/p&gt;
&lt;p&gt;Ах да, помимо этого патч убирает имя контакта в беседе. Я бота обозвал просто Twitter, соответственно в патче нужно подставить то имя, которое используете вы.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2009/09/12/gajim-i-ssyilki-v-xhtml/</guid><feedburner:origLink>http://cyxapeff.org/blog/2009/09/12/gajim-i-ssyilki-v-xhtml/</feedburner:origLink></item><item><title>Новый дизайн</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/zzXdjkNAS3A/</link><description>
&lt;p&gt;В свободное время наваял новый дизайн блогу. На этот раз минималистичный. Кстати это уже третий дизайн за всё время существования. По дизайну в год получается. По мимо этого, внутри постарался всё оптимизировать и закэшировать максимально - работать движок стал значительно быстрее. Хотя есть ещё к чему стремиться. Ругать можно в комментариях.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2009/07/31/novyij-dizajn/</guid><feedburner:origLink>http://cyxapeff.org/blog/2009/07/31/novyij-dizajn/</feedburner:origLink></item><item><title>Google Analytics и Python</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/5MwT2qvl7J0/</link><description>
&lt;p&gt;В dashboard админки моего блога показывается количество хитов, хостов и ещё кое-какая информация из статистики. А статистику ведёт гугл. Раньше я использовал &lt;a href="http://www.juiceanalytics.com/openjuice/juiced-google-analytics-api/"&gt;pyGAPI&lt;/a&gt; и не особо парился. Но недавно оно сломалось, разбираться почему было лень, тем более что уже довольно давно у Google Analytics появился свой &lt;a href="http://code.google.com/intl/ru/apis/analytics/docs/gdata/gdataDeveloperGuide.html"&gt;API&lt;/a&gt;. Вообще есть несколько python библиотек для работы с этим API, но мне больше всех понравилась &lt;a href="http://suryasev.github.com/python-degapi/"&gt;python-degapi&lt;/a&gt;. Она основана на python-gdata и очень просто позволяет получать всё что надо.
&lt;/p&gt;
&lt;p&gt;Установка элементарна. Скачиваем tar архив или клонируем git репозиторий. Если в системе ещё нет python-gdata, делаем как написано на офф сайте и устанавливаем. У меня же в ubuntu пакет python-gdata уже был установлен, поэтому файлы из архива я скопировал прямо в директорию с установленным gdata.
&lt;/p&gt;
&lt;p&gt;Ну практика лучше тысячи слов, поэтому парочка примеров. Получаем список сайтов на аккаунте:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import gdata.analytics.service
client = gdata.analytics.service.AccountsService()
client.ClientLogin('cyxapeff@gmail.com', 'mypassword')
alist = client.GetAccountList()
for account in alist.entry:
    print account.title.text # выводим название сайта
    print account.profileId # его Id
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Получаем число просмотров и посетителей с начала месяца (1234567 - как раз этот самый profileId):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import gdata.analytics.service
from datetime import date
client2 = gdata.analytics.service.AnalyticsDataService()
client2.ClientLogin('cyxapeff@gmail.com', 'mypassword')
data = client2.GetData('ga:1234567', dimensions='ga:month', metrics='ga:visits,ga:visitors',
            start_date=date.today().replace(day=1), end_date=date.today())
print data.entry[0].visits, data.entry[0].visitors
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Есть очень удобные &lt;a href="http://code.google.com/intl/ru/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html"&gt;таблички с Dimensions и Metrics&lt;/a&gt;, так же есть возможность сортировать, фильтровать результаты и брать их срезы.
&lt;/p&gt;
&lt;p&gt;Enjoy!
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2009/06/28/google-analytics-i-python/</guid><feedburner:origLink>http://cyxapeff.org/blog/2009/06/28/google-analytics-i-python/</feedburner:origLink></item><item><title>Python: sms через mail.ru</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/No5te8MIcHw/</link><description>
&lt;p&gt;Сам пользуюсь и решил поделиться. Тем более уже просили. Небольшая &lt;a href="http://cyxapeff.org/media/sms_send.zip"&gt;библиотечка&lt;/a&gt; с примером отправки смски из консоли. Почти весь код позаимствован из jabber транспорта &lt;a href="http://jabber.ru/files/mrim/"&gt;mrim&lt;/a&gt;. Поэтому там много лишнего. Никаких проверок на доставку нет. Тем более что смс не всегда доходят даже через офф клиент. Но на мои два номера на мегафоне и билайне приходят, тьфу-тьфу-тьфу, отлично.
&lt;/p&gt;
&lt;p&gt;Ну и примерчик:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import mrimsmssender
mrimsmssender.send_sms("yournick@mail.ru", "password", "+79221412345", u"Text of test sms")
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Да, вот так просто. Ну естественно нужно быть зарегистрированным на mail.ru. Enjoy!
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2009/04/21/python-sms-cherez-mailru/</guid><feedburner:origLink>http://cyxapeff.org/blog/2009/04/21/python-sms-cherez-mailru/</feedburner:origLink></item><item><title>XFCE и FTP. Делаем удобно!</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/JecFA4qiwO8/</link><description>
&lt;p&gt;С некоторых пор на моём eeepc в качестве рабочего окружения живёт и здравствует XFCE. Но его файловый менеджер Thunar не умеет работать с фтп. После гнома и всеядного наутилуса для меня это оказалось неожиданностью. Так же из-за привычки работать с фтп прямо из файлового менеджера без специальных клиентов захотелось сделать так же и тут.
&lt;/p&gt;
&lt;p&gt;Погуглив на тему thunar ftp plugin я расстроился, но быстро вспомнил, что есть же fuse! И так apt-cache search fuse ftp выдал мне несколько пакетов, не долго думая я взял curlftpfs. В общем на этом рассказ заканчивается и дальше маленький how-to.
&lt;/p&gt;
&lt;p&gt;Создаём директорию куда будем монтировать ftp.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir ~/ftp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Удобно её сунуть в Shortcuts в Thunar'е. Затем ставим curlftpfs.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install curlftpfs
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Теперь &lt;code&gt;curlftpfs host localdir&lt;/code&gt; подмонтирует фтп в куда надо. Но только из под рута. Дадим возможность монтировать и простому пользователю.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo adduser username fuse
sudo chown fuse ~/ftp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;И казалось бы всё, но не охота мне лезть каждый раз в консоль. Поэтому сделаем маленький скриптик который повесим на кнопку в панеле. (Я назвал файл .mountftp чтобы глаза не мозолил и положил в домашнюю директорию)
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/bash
host=$(zenity --title="Mount FTP" --entry --text="Host:");
if [ "$?" == "1" ]; then
  exit;
else
  fusermount -u /home/smacker/ftp;
  answer=$(curlftpfs "$host" "/home/smacker/ftp" 2&amp;gt;&amp;amp;1);
  if $answer; then
    thunar /home/smacker/ftp;
  else
   zenity --info --title="error" --text="$answer";
  fi
fi
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В качестве гуя используется zenity (в убунте она есть из коробки). Очень простая и удобная штучка. Подробнее можно посмотреть в man или ключём --help. Как видно по коду мы показываем окошко куда надо ввести хост, после этого на всякий случай отмонтируем директорию и попробуем примонтировать вновь. Если всё хорошо, то сразу же её и откроем. Если же произошла ошибка - покажем её пользователю.
&lt;/p&gt;
&lt;p&gt;Ну вот. Теперь работа с фтп из xfce не менее удобна, чем в gnome. Мне обычно нужно в один момент времени работать только с одним фтп, но если у вас их много - думаю вы разберётесь какие изменения нужно внести в скрипт.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2009/04/13/xfce-i-ftp-delaem-udobno/</guid><feedburner:origLink>http://cyxapeff.org/blog/2009/04/13/xfce-i-ftp-delaem-udobno/</feedburner:origLink></item><item><title>Парочка Twi сервисов</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/XJPC54hy2S0/</link><description>
&lt;p&gt;На досуге сделал пару сервисов для твиттера.
&lt;/p&gt;

&lt;h3&gt;RuVictory&lt;/h3&gt;
&lt;p&gt;Это по бот-викторина. Он задаёт вопросы и ждёт верные ответы реплаями. Конечно же есть рейтинг самых "умных" пользователей.
   Чтобы начать играть нужно зафолловить @&lt;a href="http://twitter.com/ruvictory"&gt;ruvictory&lt;/a&gt; и написать ему реплай или личное сообщение с верным ответом. Рейтинг есть на &lt;a href="http://cyxapeff.org/ruvictory/"&gt;страничке&lt;/a&gt; бота.
&lt;/p&gt;

&lt;h3&gt;Twitter Badges&lt;/h3&gt;
&lt;p&gt;Для нашей екб-тви-сходки я делал бэйджики для всех. Естественно не ручками, а набросав быстренько скриптик. Выбрасывать его жаль, поэтому оформил его в виде &lt;a href="http://cyxapeff.org/twibadges/"&gt;сервиса&lt;/a&gt;. Просто вводите свой ник и получаете картинку которую можно засунуть в бэйджик. Так же можно ввести сразу несколько ников и скачать картинки одним архивом.
&lt;/p&gt;
&lt;p&gt;В обоих случаях использован питон и django. API твиттера даёт возможность забирать данные в виде xml и json. И один из сервисов использует xml, другой json. Как оказалось с json'ом работать гораздо удобней.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2009/04/04/parochka-ti-servisov/</guid><feedburner:origLink>http://cyxapeff.org/blog/2009/04/04/parochka-ti-servisov/</feedburner:origLink></item><item><title>сборка QutIM 0.2</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/x4T2pYjQ0gc/</link><description>
&lt;p&gt;Вообще в сборке &lt;a href="http://qutim.org"&gt;qutim&lt;/a&gt; ничего особо сложного нет. Но как минимум придётся убить минут двадцать на изучение официального форума. И то не всё сразу найдёшь. Поэтому рассмотрим сборку qutim с плагинами ICQ и Jabber, звуками, смайликами, русским языком и всё это под Ubuntu.
&lt;/p&gt;
&lt;p&gt;1) Нужно поставить необходимые для сборки пакеты. Я даже специально поставил Ubuntu 8.10 в виртуальную машину для чистоты эксперимента.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install subversion cmake g++ libqt4-dev libgnutls-dev
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;2) Заберём из svn последнюю версию кутима и плагинов.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;svn co http://qutim.org/svn/qutim
cd qutim/plugins
svn co http://qutim.org/svn/icq
svn co http://qutim.org/svn/jabber
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;3) Собираем ядро.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd qutim
cmake ./
make
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;4) Собираем icq плагин.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd plugins/icq
qmake
make
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;5) Собираем jabber плагин.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd plugins/jabber
cmake -DGNUTLS=1 -DZLib=1 ./
make
mv libjabber.so ../
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Tip: Ничто не мешает всё это собирать одновременно. :)
&lt;/p&gt;
&lt;p&gt;6) Скачиваем русский
&lt;/p&gt;
&lt;p&gt;Последнюю версию можно найти в &lt;a href="http://www.qutim.org/forum/viewtopic.php?f=63&amp;amp;t=714"&gt;теме на форуме&lt;/a&gt;.&lt;br /&gt;
Распаковываем и кладём папочку languages в директорию с qutim.
&lt;/p&gt;
&lt;p&gt;7) Смайлики
&lt;/p&gt;
&lt;p&gt;Паки смайлов лежат на &lt;a href="http://qutim.org/look-n-feel?hierarchy=8"&gt;официальном сайте&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Лично я взял Big kolobok pack.
&lt;/p&gt;
&lt;p&gt;Создаём директорию emoticons. И распаковываем туда пак. В результате у нас получится, что icondef.xml лежит в
   qutim/emoticons/Packname/icondef.xml
&lt;/p&gt;
&lt;p&gt;8) Звуки
&lt;/p&gt;
&lt;p&gt;Так же берём на &lt;a href="http://qutim.org/look-n-feel?hierarchy=9"&gt;офф сайте&lt;/a&gt;&lt;br /&gt;
Куда их класть, впринципе, не важно. Лично я положил в qutim/sounds
&lt;/p&gt;
&lt;p&gt;Ну, наконец, запускаем ./qutim&lt;br /&gt;
Сначала он спросит название и пароль для профиля. Дальше предложит добавить icq и jabber аккаунты. После выполнения этих не хитрых действий, лезем в "User interface settings" ("Оформление"). Ставим русский язык и смайл пак. В основных настройках, на вкладке "Sound notifications" ("Звуковые события"), жмём импорт и указываем куда распаковали звуки.
&lt;/p&gt;
&lt;p&gt;Ну вот вообщем и всё. Enjoy!
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2009/03/20/sborka-qutim-02/</guid><feedburner:origLink>http://cyxapeff.org/blog/2009/03/20/sborka-qutim-02/</feedburner:origLink></item><item><title>smtp debug</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/woiFUWaKXZE/</link><description>
&lt;p&gt;Сегодня закрыли Ticket &lt;a href="http://code.djangoproject.com/ticket/8638"&gt;#8638&lt;/a&gt;, &lt;a href="http://code.djangoproject.com/changeset/9793"&gt;рекомендуя&lt;/a&gt; использовать команду
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python -m smtpd -n -c DebuggingServer localhost:1025
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;которая запустит простой SMTP сервер, выводящий заголовки и содержимое письма в консоль. По-моему очень удобно. Когда мне самому понадобилось дебажить функции рассылающие письма, пришлось устанавливать и настраивать postfix с dovecot. Теперь их можно спокойно снести.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2009/01/29/smtp-debug/</guid><feedburner:origLink>http://cyxapeff.org/blog/2009/01/29/smtp-debug/</feedburner:origLink></item><item><title>Голосование</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/cC3HDdg_Tcw/</link><description>
&lt;p&gt;Пришло &lt;a href="http://internetno.net/2008/12/26/vtoroy-tur-novogodnego-postopisatelstva-2008/#comments"&gt;время голосовать&lt;/a&gt; за посты новогоднего постописательства от интернетных штучек.
&lt;/p&gt;
&lt;p&gt;Для себя выделил 2 поста:
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;
     Bright: &lt;a href="http://freealt.net/2008/12/24/poleznee-vseh-tot-kto-znaet-mnogo-obo-vsem/"&gt;Полезнее всех тот, кто знает много обо всем&lt;/a&gt; - гугл.ру в стихах. Да ещё каких :)
 &lt;/li&gt;

 &lt;li&gt;
     rutwitter: &lt;a href="http://www.rutwitter.com/vyi-hotite-trafik-ih-est-u-menya/"&gt;Вы хотите трафик? Их есть у меня…&lt;/a&gt; - написано про мой ставший любимым твиттер, да ещё и узнал о Корице.
 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Надеюсь, за меня кто-нибудь тоже проголосует :DDD
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/12/26/golosovanie/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/12/26/golosovanie/</feedburner:origLink></item><item><title>Что почитать? Что посмотреть?</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/Z3JYDSzfPN8/</link><description>
&lt;p&gt;У меня частенько возникает этот вопрос. Из всего многообразия книг и фильмов очень сложно выбрать что-то одно. И обычно я лезу в аську спрашивать у друзей, что им понравилось из того, что они недавно читали\смотрели. К сожалению, далеко не всегда наши вкусы сходятся. Но есть такой замечательный сервис &lt;a href="http://imhonet.ru"&gt;Imhonet&lt;/a&gt;, после того как вы поставите несколько оценок, он начинает искать пользователей с похожими вкусами и рекомендовать вам то, что они высоко оценили. Есть разные фильтры: по жанрам, дате, количеству оценок, количеству рекомендателей, предполагаемой оценки. И это работает! Таким образом я нашёл ни одну интересную книгу.
&lt;/p&gt;
&lt;p&gt;Для большинства представленных в каталоге  фильмов и книг есть краткое описание, отзывы. Что так же сильно помогает в выборе.
&lt;/p&gt;
&lt;p&gt;Ну а дружба с другими пользователями избавит от вопросов по аське. Вся лента как на ладони.
&lt;/p&gt;
&lt;p&gt;Что радует, сервис постоянно развивается. Например, изменён дизайн, появились сообщества, блоги и взят курс на большую социальность. Помимо художественной литературы и фильмов присутствует большое количество других разделов, таких как "Музыка", "Сцена", "Игры", "Вино" и другие. Новые разделы появляются довольно часто. (правда я ими не пользуюсь) Конечно не всё гладко, постоянные изменения приводят к частым багам (но исправляются довольно быстро), отсутствует какой бы то ни было экспорт своей коллекции или рекомендаций (решаемо &lt;a href="http://cyxapeff.org/blog/2008/12/13/imhonet-opyat/"&gt;всякими костылями&lt;/a&gt;).
&lt;/p&gt;
&lt;p&gt;А этот пост написан в рамках &lt;a href="http://internetno.net/2008/12/19/4323/"&gt;Новогоднего постописательства 2008&lt;/a&gt; от Интернетных штучек.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/12/20/chto-pochitat-chto-posmotret/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/12/20/chto-pochitat-chto-posmotret/</feedburner:origLink></item><item><title>Модуль рекомендаций для друпала</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/LqsAeWL3M28/</link><description>
&lt;p&gt;К одному моему сайту прикрутил недавно возможность голосовать за материалы, ну и соответственно в зависимости от количества голосов формируется главная страница. Но так как сайт маленький, кое-какие записи хотелось выводить сразу вне зависимости от того голосовал кто-нибудь или нет. Долго искал как это сделать. Просмотрел кучу модулей, наигрался с views, но ничего не вышло. Пришлось писать свой модуль.
&lt;/p&gt;
&lt;p&gt;Умеет:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Рисовать симпатичный виджет, клик по которому рекомендует или снимает рекомендацию.
 &lt;/li&gt;

 &lt;li&gt;
     Выводить записи суммарная оценка которых выше N.
 &lt;/li&gt;

 &lt;li&gt;
     Выводить собственно рекомендованные записи
 &lt;/li&gt;

 &lt;li&gt;
     Выводить записи определённых ролей
 &lt;/li&gt;

 &lt;li&gt;
     Работать только с выбранными типами материалов
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Естественно все "фильтры" объединены логическим оператором ИЛИ.
&lt;/p&gt;
&lt;p&gt;Если вдруг кому-то нужно такую штуку - &lt;a href="http://cyxapeff.org/media/recommend.zip" title="Download"&gt;забираем&lt;/a&gt;.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/12/17/modul-rekomendatsij-dlya-drupala/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/12/17/modul-rekomendatsij-dlya-drupala/</feedburner:origLink></item><item><title>Imhonet опять</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/_WtrLD8h9iU/</link><description>
&lt;p&gt;Я уже &lt;a href="http://cyxapeff.org/blog/2008/08/26/poslednie-knigi-s-imhonet/" title=""&gt;писал&lt;/a&gt; об этом, но после редизайна всё естественно сломалось. Теперь наконец дошли руки подкрутить парсер, чтобы он мог разбирать новый дизайн.
&lt;/p&gt;
&lt;p&gt;И теперь оно умеет и фильмы тоже выводить. Пример:
   &lt;script type="text/javascript" src="http://cyxapeff.org/imhonet/cyxapeff/widget/?n=5&amp;t=movie"&gt;&lt;/script&gt;
   &lt;div id="imhoMovieWidget" style="margin-left:50px;"&gt;&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;А теперь как вставить к себе, книжки:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type="text/javascript" src="http://cyxapeff.org/imhonet/[Name]/widget/?n=[N]&amp;amp;t=book"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;div id="imhoBookWidget"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Фильмы:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type="text/javascript" src="http://cyxapeff.org/imhonet/[Name]/widget/?n=[N]&amp;amp;t=movie"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;div id="imhoMovieWidget"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;[Name] - ваш ник на imhonet'е
   [N] - колличество элементов
&lt;/p&gt;
&lt;p&gt;Просто json можно забрать аналогично:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://cyxapeff.org/imhonet/[Name]/json/?n=[N]&amp;amp;t=book
http://cyxapeff.org/imhonet/[Name]/json/?n=[N]&amp;amp;t=movie
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Update&lt;/h3&gt;
&lt;p&gt;Появился экспорт в xml и rss.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://cyxapeff.org/imhonet/[Name]/xml/?n=[N]&amp;amp;t=book
http://cyxapeff.org/imhonet/[Name]/rss/?n=[N]&amp;amp;t=movie
&lt;/code&gt;&lt;/pre&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/12/13/imhonet-opyat/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/12/13/imhonet-opyat/</feedburner:origLink></item><item><title>ну вот и я, Twitter</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/JZiPVFLICFM/</link><description>
&lt;p&gt;Узнал что такое twitter ещё пару лет назад, но не видел для себя смысла в его использовании. Ну и собственно не пользовался. А вот сейчас "созрел". Я всё под тем же ником, так что можно писать мне и туда @&lt;a href="http://twitter.com/cyxapeff" title="cyxapeff"&gt;cyxapeff&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Да, сразу же прикрутил его к этому блогу. Вверху можно видеть мой последний статус.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/12/12/nu-vot-i-ya-titter/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/12/12/nu-vot-i-ya-titter/</feedburner:origLink></item><item><title>Imageshack.us applet v0.4</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/Qmdg95UAZ30/</link><description>
&lt;p&gt;Доделал версию 0.4.
&lt;/p&gt;
&lt;p&gt;Изменения с версии 0.1:
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;&lt;p&gt;Поддержка различных фотохостингов. Из коробки поддерживает imageshack.us, tinypic.com, ipicture.ru, radikal.ru. Реализовано плагинами, так что прикрутить поддержку любого другого фотохостинга дело 10 минут.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Шаблоны вывода. Можно создавать, изменять, удалять шаблоны.
   Сразу созданы:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Простая ссылка на картинку
 &lt;/li&gt;

 &lt;li&gt;
     Ссылка на страничку, которая показывается после загрузки изображения
 &lt;/li&gt;

 &lt;li&gt;
     Html код
 &lt;/li&gt;

 &lt;li&gt;
     BB код
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если необходимо можно добавить, например, markdown разметку.
   В шаблоне доступны переменные:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     %image% - ссылка на картинку
 &lt;/li&gt;

 &lt;li&gt;
     %ad% - ссылка на страничку
 &lt;/li&gt;

 &lt;li&gt;
     %thumb% - ссылка на миниатюру
 &lt;/li&gt;

 &lt;li&gt;
     %filename% - имя файла на хосте
 &lt;/li&gt;
&lt;/ul&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;История загрузок.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Скриншот экрана. (Shift + click или клик колёсиком)
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Многоязычность. Сразу есть русский и английский языки.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Отображение самого апплета в виде иконки, текста или того и другого одновременно.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;В диалоге выбора файлов сделан фильтр только изображений, а так же сразу показывается миниатюра.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;При drag&amp;amp;drop так же в диалоге подтверждения отображается миниатюра.
&lt;/p&gt;

 &lt;/li&gt;

 &lt;li&gt;&lt;p&gt;Добавлены отступы, соответсвенно выглядят окошки симпотичней.
&lt;/p&gt;

 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Скачать: &lt;a href="http://code.google.com/p/imageshack-applet/downloads/list" title="download"&gt;deb-пакет или исходники&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Так же можно стянуть из &lt;a href="http://imageshack-applet.googlecode.com/svn/trunk/"&gt;svn&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Практически всё что хотел реализовал, так что дальше апплет, скорей всего, развиваться не будет.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/12/06/imageshackus-applet-v04/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/12/06/imageshackus-applet-v04/</feedburner:origLink></item><item><title>Imageshack.us applet</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/bP43xuHZxqU/</link><description>
&lt;p&gt;Довольно часто необходимо показать кому-нибудь фотографию или скрин. Самое простое - воспользоваться каким-нибудь фотохостингом. Но очень лениво каждый раз набирать http://imageshack.us или http://tinypic.com, а потом выискивать нужный файл. Захотелось как-нибудь это дело упростить. Первая мысль - должен быть апплетик к gnome panel, с помощью которого всё было бы гораздо проще. Поискал в гугле, но, на удивление, ничего не нашёл. Пришлось написать самому.
&lt;/p&gt;
&lt;p&gt;Итак. Встречаем &lt;strong&gt;Imageshack.us Applet&lt;/strong&gt;!
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://cyxapeff.org/media/blog/img/applet-screenshot1.png" title="Imageshack.us Applet" alt="Imageshack.us applet"/&gt;
&lt;/p&gt;
&lt;p&gt;Собственно вот эта надпись "Host it!" и есть весь апплет. Если щёлкнуть на него левой клавишей - выскочит обыкновенное окошко с выбором файла. После выбора он сразу начнёт загружать изображение на сервер.
   Так же поддерживается Drag&amp;amp;Drop. Просто перетащите картинку на эту надпись, апплет тут же спросит действительно ли вы хотите выложить этот файл (вдруг случайно не там отпустили его), если всё верно, то начнётся upload.
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://cyxapeff.org/media/blog/img/applet-screenshot2.png" title="Imageshack.us Applet Dialog" alt="Imageshack.us applet Dialog"/&gt;
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://cyxapeff.org/media/blog/img/applet-screenshot3.png" title="Imageshack.us Applet Uploading" alt="Imageshack.us applet Uploading"/&gt;
&lt;/p&gt;
&lt;p&gt;После того как изображение загрузится появится окошко с миниатюрой, ссылочками и кодом.
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://cyxapeff.org/media/blog/img/applet-screenshot4.png" title="Imageshack.us Applet" alt="Imageshack.us applet"/&gt;
&lt;/p&gt;
&lt;p&gt;Чтобы скопировать ссылку (или код) нужно щёлкнуть по нему, он сразу окажется в буфере обмена.
&lt;/p&gt;
&lt;p&gt;Скачать: &lt;a href="http://cyxapeff.org/media/imageshack.us_0.2-1_i386.deb" title="скачать"&gt;deb пакет&lt;/a&gt; или &lt;a href="http://cyxapeff.org/media/imageshack.us-0.2.tar.bz2" title="Скачать"&gt;исходники&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Требует python 2.5 и PIL&lt;/em&gt;
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/11/26/imageshackus-applet/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/11/26/imageshackus-applet/</feedburner:origLink></item><item><title>Последние книги с imhonet</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/tL52eaNhdBI/</link><description>
&lt;h3&gt;Всё что написано ниже уже не работает&lt;/h3&gt;
&lt;p&gt;Есть такой интересный сервис &lt;a href="http://imhonet.ru"&gt;imhonet.ru&lt;/a&gt;, он позволяет оценивать книги\фильмы\всякое другое, а так же на основе этих оценок даёт рекомендации. И всё бы хорошо, но мне захотелось показывать последние прочитанные книжки в блоге, а имхонет никак не отдаёт данные. Пришлось написать небольшой парсер, который в результате отдаёт json который элементарно разбирается где угодно. Сделал его отдельным django приложением, а так же нарисовал маленький виджет. Посмотреть на него можно в разделе "&lt;a href="http://cyxapeff.org/blog/about/"&gt;обо мне&lt;/a&gt;".
&lt;/p&gt;
&lt;p&gt;Если тоже есть желание доставать оттуда книжки, то ссылочка http://cyxapeff.org/imhonet/%username%/json/?n=%n% поможет (где %username% соответственно ваш ник на imhonet, а %n% колличество книжек). (естественно оно кэшируется, кэш обновляется каждые 6 часов)
&lt;/p&gt;
&lt;p&gt;Если лень разбирать json, можно повесить такой же виджет как у меня. Вставляется он так (требует jquery):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type="text/javascript" src="http://cyxapeff.org/imhonet/%username%/widget/?n=%n%"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;div id="imhonetWidget"&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/08/26/poslednie-knigi-s-imhonet/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/08/26/poslednie-knigi-s-imhonet/</feedburner:origLink></item><item><title>Наконец-то обновил блог</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/msXxVEQo350/</link><description>
&lt;p&gt;Наконец дошли руки залить все изменения в блоге на сервер. Изменений куча. Но большинство из них внутренние (проверка коммента на спам с помощью akismet, полноценная своя админка и тд). Для пользователя же видно:
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;
     Новая форма для комментариев. Теперь можно использовать markdown и получать уведомления о новых комментариях.
 &lt;/li&gt;

 &lt;li&gt;
     Прикручено новое приложение: портфолио.
 &lt;/li&gt;

 &lt;li&gt;
     Облако тегов по другому формируется.
 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Как обычно оно плохо протестировано, так что может отдавать ошибки.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/08/26/nakonets-to-obnovil-blog/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/08/26/nakonets-to-obnovil-blog/</feedburner:origLink></item><item><title>Google Insights for Search</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/9mRwdRnkzUc/</link><description>
&lt;p&gt;Гугл показал свой новый сервис &lt;a href="http://www.google.com/insights/search/"&gt;Google Insights for Search&lt;/a&gt; и первое что пришло на ум посмотреть это частату запросов по django. Вполне логично что за последние 2 года интерес растёт, но что меня порадовало: по запросам "django" и "django python" на первом месте Russian Federation. Хотя судя по сайтам о джанго, русское сообщество далеко не самое большое.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/08/07/google-insights-for-search/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/08/07/google-insights-for-search/</feedburner:origLink></item><item><title>Django-fileman</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/RBgGrPnmZsA/</link><description>
&lt;p&gt;Я уже &lt;a href="http://cyxapeff.org/blog/2007/11/29/izvraschaemsya-na-django/" title="посмотреть"&gt;писал&lt;/a&gt; о моём &lt;a href="http://code.google.com/p/django-fileman/"&gt;файловом менеджере&lt;/a&gt; на Django+jQuery.
   И вообщем-то с того времени я его и не трогал. А тут вот ещё немного покрутил. Конечно это по прежнему глючная, недоделанная поделка, но теперь банановая! Всмысле умеет показывать текстовые файлы и картинки, а так же даёт скачать любой файлик.
&lt;/p&gt;
&lt;p&gt;Выглядит это примерно так:
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/File_Manager_1213365285400.png"&gt;&lt;img src="http://cyxapeff.org/media/File_Manager_1213365285400_trumb.png" alt="View source"/&gt;&lt;/a&gt; &lt;a href="http://cyxapeff.org/media/File_Manager_1213365262960.png"&gt;&lt;img src="http://cyxapeff.org/media/File_Manager_1213365262960_trumb.png" alt="Image preview"/&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Ну и кому интересно - внутри оно тоже чуток красивее стало.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/06/13/django-fileman/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/06/13/django-fileman/</feedburner:origLink></item><item><title>wrTorrent.py</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/Kmq1D-acnXA/</link><description>
&lt;p&gt;Пишу свою веб морду к rTorrent. Конечно же на питоне.
   В качестве фреймворка взял лёгкий и удобный web.py, после джанго ощущения довольно смешанные. В отличии от django этот фреймворк практически ни к чему не принуждает, научится работать с ним гораздо проще. Но шаблоны после джанговских настолько неудобные...
&lt;/p&gt;
&lt;p&gt;Вернёмся к wrTorrent.py (да, я знаю, что название убогое :)), это такой пробничек. На данный момент умеет только показываеть все торренты, добавлять, останавливать, возобновлять и удалять их. Никаких красявостей или ajax'a пока нет.
&lt;/p&gt;
&lt;p&gt;Выглядит это вот так:
&lt;/p&gt;
&lt;p&gt;&lt;a href="/media/wrTorrent.py.png"&gt;&lt;img src="/media/wrTorrent.py_trumb.png"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Если кому-нибудь интересно на это посмотреть вблизи, милости прошу: &lt;a href="http://cyxapeff.org/media/wrTorrent.py-0.0.1.tar.gz"&gt;wrTorrent.py-0.0.1.tar.gz&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;Установка&lt;/h2&gt;
&lt;ol&gt;
 &lt;li&gt;
     Включите в rtorrent поддержку scgi. (как это делается можно прочитать на &lt;a href="http://libtorrent.rakshasa.no/wiki"&gt;офф сайте&lt;/a&gt;)
 &lt;/li&gt;

 &lt;li&gt;
     Установите web.py 0.22 (&lt;a href="http://webpy.org"&gt;http://webpy.org&lt;/a&gt;)
 &lt;/li&gt;

 &lt;li&gt;
     Запустите wrTorrent.py коммандой "python code.py" или "python code.py порт" (порт по умолчанию 8080)
 &lt;/li&gt;

 &lt;li&gt;
     Откройте в браузере http://domain:port/settings/
     Настройки:
     Protocol: scgi или xmlrpc (первый возможно использовать только если rtorrent и wrtorrent.py запущены на одной машине)
     URL: адрес rtorrent (example: scgi://127.0.0.1:5000 или http://192.168.0.2)
     Domain: адрес wrtorrent.py, к нему обращается rtorrent, чтобы забрать torrent файл, который вы загрузили с помощью кнопочки "обзор".
 &lt;/li&gt;

 &lt;li&gt;
     Всё. http://domain:port/ - можно пользоваться.
 &lt;/li&gt;
&lt;/ol&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/01/13/rtorrentpy/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/01/13/rtorrentpy/</feedburner:origLink></item><item><title>Rss потоки с torrents.ru</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/-0rcmt0u4vI/</link><description>
&lt;h3&gt;Завязка&lt;/h3&gt;
&lt;p&gt;Всем известно, что популярный bit torrent треккер torrents.ru не предоставляет rss потоки с новыми темами на форуме. Естественно это очень не удобно. Приходится постоянно заходить на сайт и просматривать чего нового появилось + высок шанс чего-нибудь интересного пропустить. Попользовавшись поиском по форуму я понял, что в ближайшее время rss особо не планируется. Поэтому я написал очередной небольшой велосипедик.
&lt;/p&gt;

&lt;h3&gt;Принцип работы&lt;/h3&gt;
&lt;p&gt;Каждые 15 минут сервис скачивает первую страницу нужного форума, выдирает все темы, проверяет есть ли такая темы в его базе данных и если нет, то добавляет. Естественно он может пропускать темы при большой активности на форуме или при длительной недоступности torrents.ru, но в общем справляется со своими обязаностями.
&lt;/p&gt;

&lt;h3&gt;Тоже так хочу!&lt;/h3&gt;
&lt;p&gt;Тогда скачиваем &lt;a href="http://cyxapeff.org/media/torrentsrss.tar.gz"&gt;этот&lt;/a&gt; архивчик, прикручиваем его к django проекту. Не забываем в cron.py прописать свою куку и суём его в крон. Затем через админку добавляем интерисующие нас форумы. Вуаля. Фиды можно добавлять в свой любимый агрегатор.
&lt;/p&gt;
&lt;p&gt;Посмотреть на это в действии можно у меня: &lt;a href="http://home.cyxapeff.org/trss/"&gt;http://home.cyxapeff.org/trss/&lt;/a&gt;
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2008/01/05/rss-potoki-s-torrentsru/</guid><feedburner:origLink>http://cyxapeff.org/blog/2008/01/05/rss-potoki-s-torrentsru/</feedburner:origLink></item><item><title>С новым годом!</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/RLTFLAjCh-8/</link><description>
&lt;p&gt;Поздравляю всех посетителей моего блога с новым 2008 годом!&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/12/31/s-novyim-godom/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/12/31/s-novyim-godom/</feedburner:origLink></item><item><title>Обновление</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/R1gJCrnqXbM/</link><description>
&lt;p&gt;Нарисовал новый дизайн и прикрутил "темы" к блогу.
&lt;/p&gt;
&lt;p&gt;Сменил урлы записей. Исправил баги, уменьшил колличество запросов к базе данных в несколько раз.
   Думаю уже скоро будет не стыдно и исходный код показать. :)
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/12/17/obnovlenie/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/12/17/obnovlenie/</feedburner:origLink></item><item><title>Извращаемся на django</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/aIy7iUynV1E/</link><description>
&lt;p&gt;Сделал тут файловый менеджер на django + jQuery. :D
&lt;/p&gt;
&lt;p&gt;Очень сырой, но в общем - работает...
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.google.com/p/django-fileman/"&gt;Посмотреть код и скриншоты&lt;/a&gt;
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/11/29/izvraschaemsya-na-django/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/11/29/izvraschaemsya-na-django/</feedburner:origLink></item><item><title>Пишем Tv программу на Django. Часть 4</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/cbX6kUBds_s/</link><description>
&lt;p&gt;Ну вот, не прошло и пол года и новая часть рассказа о создания tv программы готова. :)
&lt;/p&gt;
&lt;p&gt;В этой части мы будем обвешивать нашу программку javascript'ом.
   И ещё немножко всякого интересного.
&lt;/p&gt;
&lt;p&gt;В первую очередь уберём маленькую недоработочку. А именно, я совсем забыл при нажатиях по кнопкам менять режим у пользователя с "Показывать только актуальные" на "Показывать все". И наоборот. Для исправления нужно всего лишь в функциях &lt;code&gt;day&lt;/code&gt; и &lt;code&gt;chanal&lt;/code&gt; дописать:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    if request.GET.has_key("allday"):
        setting.Mode = 1
        setting.save()
    elif request.GET.has_key("new"):
        setting.Mode = 0
        setting.save()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ну и в шаблоне ссылку с &lt;code&gt;?&lt;/code&gt; поменять на &lt;code&gt;?new&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;Так же хочу сообщить, что тв программка стала чуть-чуть посимпатичней. Дизайн переделал опираясь на тему админки. Даже css и картинки почти полностью оттуда содраны. Выглядит главная страничка теперь примерно так:
&lt;/p&gt;
&lt;p&gt;&lt;a href="/media/blog/img/tvwatcher.png"&gt;&lt;img src="/media/blog/img/tvwatcher_trumb.png"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Правда мне было очень-очень лень доделать всё это поэтому нормально смотрится оно пока только в ff. Ну и валидацию, я думаю вряд ли пройдёт. Но со временем всё исправится.
&lt;/p&gt;
&lt;p&gt;Вернёмся к ajaxизации. Для этого я использовал очень удобный framework под названием &lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt;. В общем-то какой фреймворк использовать или вообще его не использовать решать только Вам, т.к django это без разницы. Но мне нравится jQuery, поэтому все примеры будут на нём.
&lt;/p&gt;
&lt;p&gt;Итак, что я хочу делать при помощи javascript:
   1. Формочки входа и регистрации должны появляться без перезагрузки страницы.
   2. Добавлять\Удалять каналы с главной страницы так же нужно без перезагрузки.
   3. Должна быть возможность "таскать" эти самые каналы по страничке.
   4. На странице с одиночным каналом информация о фильме должна подгружаться при наведении курсора на строчку с фильмом.
   5. Чуть-чуть оживить всё разными эффектами.
&lt;/p&gt;
&lt;p&gt;Для этого мне понадобился помимо самой jQuery довольно большой список плагинов. Вот вырезка из &lt;code&gt;base.html&lt;/code&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type="text/javascript" src="/media/jquery.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="/media/ui/jquery.dimensions.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="/media/ui/ui.mouse.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="/media/ui.draggable.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="/media/ui.droppable.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="/media/ui/ui.sortable.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="/media/thickbox-compressed.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type="text/javascript" src="/media/tv/tv.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Плагины начинающиеся с &lt;code&gt;ui&lt;/code&gt;, а так же &lt;code&gt;jquery.dimensions.js&lt;/code&gt; это стандартные &lt;a href="http://ui.jquery.com"&gt;jQuery UI&lt;/a&gt; плагины. Эта библиотечка позволяет без труда использовать различные визуальные эффекты на своём сайте. Подробнее можно прочитать на офф сайте. &lt;a href="http://jquery.com/demo/thickbox/"&gt;Thickbox&lt;/a&gt; это плагин реализующий нечто вроде popup'а. Ну а &lt;code&gt;tv.js&lt;/code&gt; это собственно мой код.
&lt;/p&gt;
&lt;p&gt;Т.к. я хочу оставить возможность без проблем пользоваться сайтом и тем у кого js отключён, то ссылки напрямую я не переписываю, а использую встроенную в jQuery функцию &lt;code&gt;ready&lt;/code&gt;.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$(document).ready(function() {
    $("#a_log").attr("href", "#TB_inline?height=110&amp;amp;width=250&amp;amp;inlineId=log_form");
    $("#a_reg").attr("href", "#TB_inline?height=150&amp;amp;width=250&amp;amp;inlineId=reg_form");
    $("#a_addchannel").attr("href", "javascript:getNewChannels();");
    $(".actions &amp;gt; a").each(function() {
        t = $(this).attr("href").split("/")
        $(this).attr("href", "javascript:del("+t[$(t).size()-2]+");");
    });
    $(".one &amp;gt; ul &amp;gt; li &amp;gt; a").each(function() {
        $(this).attr("onmouseover", 'get_description("'+$(this).attr('href')+'");');
    });
    $("#channelsList").sortable({change: newPlaces, hoverClass: "hover" });
});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как видно эта функция после загрузки документа переопределяет ссылки и применяет функцию &lt;code&gt;sortable&lt;/code&gt; к списку.
&lt;/p&gt;
&lt;p&gt;Первые две строчки заставляют выскакивать формы входа и регистрации. Которые до этого и так существовали на странице, но были скрыты. Для красоты используется Thickbox. Вот так оно выглядит:
   &lt;a href="/media/blog/img/tvwatcher4.png"&gt;&lt;img src="/media/blog/img/tvwatcher4_trumb.png"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Сами же формы при отправки данных просто переходят на другую страницу. Так что ничего интересного здесь нет.
&lt;/p&gt;
&lt;p&gt;А вот на добавлении каналов я остановлюсь чуть подробнее.
   При нажатии на ссылку "Добавить канал" выполняется функция &lt;code&gt;getNewChannels()&lt;/code&gt; задача которой получить с сервера список ещё не добавленных на главную страницу каналов и изменении этой ссылки в список с этими каналами, либо в сообщении что каналов больше нет.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function getNewChannels() {
    $("#addchannel").text("Подождите...");
    $.get('/tv/addchannels/?xhr', successNewChannels);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Первой строчкой меняем ссылку на просьбу подождать, второй выполняем get запрос на сервер по адресу &lt;code&gt;/tv/addchannels&lt;/code&gt;, указав параметр xhr. Когда ответ получен вызывается callback функция &lt;code&gt;successNewChannels&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;Итак, что же должен возвращать сервер. Функция &lt;code&gt;addchannels&lt;/code&gt; у нас уже существовала. Я её лишь немного переделал:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@login_required
def addchannels(request):
    xhr = request.GET.has_key('xhr') # Смотрим пришёл нам запрос с параметром xhr или без
    user=request.user
    setting = user.tv_Setting
    userchannels = []
    for place in setting.Channels.all():
        userchannels.append(place.Channel)
    channels=[]
    for channel in Channel.objects.all():
        if not channel in userchannels:
            channels.append(channel)
    if xhr: # Если с параметром, то отдаём xml, а не html.
        out = '&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;\n'
        out += '&amp;lt;channels&amp;gt;'
        for channel in channels:
            out += '&amp;lt;channel id="%d"&amp;gt;%s&amp;lt;/channel&amp;gt;' % (channel.id, channel.Title)
        out += '&amp;lt;/channels&amp;gt;'
        return HttpResponse(out, "text/xml")
    else:
        c = {
            "date": None,
            "display": user.tv_Setting.Mode,
            "user": user,
            "newchannels": channels,
            "channel": None,
        }
    return render_to_response('tv/addchannels.html', c)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;По большому счёту, я думаю по коду всё понятно. Но всё же я остановлюсь на некоторых моментах. Декоратор &lt;code&gt;@login_required&lt;/code&gt; заменяет используемую до этого конструкцию &lt;code&gt;if request.user.is_authenticated() ... else&lt;/code&gt;. Если пользователь не авторизован он автоматически отсылается на страницу входа. При асинхронном запросе я отдаю xml, хотя это не принципиально. Вы вполне можете использовать JSON, XML или даже plain text для возвращения данных. Что джанго, что любая приличная js библиотека позволяет работать и с тем и с другим и с третьим без особого труда. Мне же показалось здесь самым логичным использовать xml. Т.к. код очень простой, я не стал использовать какие-то библиотеки, а просто в переменную сразу пишу текст с тегами.
&lt;/p&gt;
&lt;p&gt;И так, xml отправлен клиенту и &lt;code&gt;successNewChannels&lt;/code&gt; принимается его обрабатывать.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function successNewChannels(xml) {
    channels = $("channel", xml);
    if (channels.size()&amp;gt;0) {
        result='&amp;lt;select id="select_newchannel"&amp;gt;';
        channels.each(function() {
            result=result+'&amp;lt;option value="'+$(this).attr("id")+'"&amp;gt;'+$(this).text()+'&amp;lt;/option&amp;gt;';
        }
        );
        result+='&amp;lt;/select&amp;gt;&amp;lt;input type="button" onclick="AddChannel()" value="Добавить"&amp;gt;';
    }
    else {
        result="Нет каналов";
    }
    $("#addchannel").html(result);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Мне кажется очень удобной фишкой jQuery это обрабатывать что угодно (html, xhtml, xml) при помощи синтаксиса css3. Хотя в данном конкретном примере это и не используется. Ну вот, список мы сформировали, показали его пользователю он чего-то выбрал и нажал кнопочку "Добавить".... И что же происходит? Да почти в точности тоже самое:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function AddChannel() {
    channel = $('#select_newchannel').val();
    $("#addchannel").text("Подождите...");
    $.post('/tv/addchannel/?xhr', {'select_newchannel': channel, 'date': current_date}, successAddChannel);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Только на этот раз мы посылаем не get, а post запрос. А так же сообщаем серверу дату, за которую нас программа интерисует.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@login_required # а ТЫ авторизирован?!
def addchannel(request):
    user=request.user
    if request.POST:
        if request.POST.has_key('select_newchannel'):
            channel=get_object_or_404(Channel, id=request.POST['select_newchannel']) # достаём канал из базы по его id, или 404.
            place = createPlace(user, channel) # создаём place
            user.tv_Setting.Channels.add(place) # и добавляем его юзеру
            xhr = request.GET.has_key('xhr')
            if xhr:
                channel = get_channel(user.tv_Setting.Mode, request.POST['date'], channel)
                out = '&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;\n'
                out += '&amp;lt;channel&amp;gt;'
                out += '&amp;lt;title id="%d" slug="%s" img="%s"&amp;gt;%s&amp;lt;/title&amp;gt;' % (channel.id, channel.Slug, channel.Icon, channel.Title)
                out += '&amp;lt;programs&amp;gt;'
                for program in channel.programs:
                    out += '&amp;lt;program time="%s"&amp;gt;%s&amp;lt;/program&amp;gt;' % (program.Time, program.Title)
                out += '&amp;lt;/programs&amp;gt;'
                out += '&amp;lt;/channel&amp;gt;'
                return HttpResponse(out, "text/xml")
        elif request.POST.has_key('schannel'):
            for id in request.POST.getlist('schannel'):
                channel=get_object_or_404(Channel, id=int(id))
                place = createPlace(user, channel)
                user.tv_Setting.Channels.add(place)
    if request.GET.has_key("next"):
        return HttpResponseRedirect(request.GET['next'])
    return HttpResponseRedirect('/tv/') # кидаем на главную
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В точности так же возвращаем xml. И разбираем его формируя уже html код.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function successAddChannel(xml) {
    $("#channelsList").sortableDestroy();
    if ($("#channelsList &amp;gt; li").size()==0) {
        $("#channelsList").html("");
    }
    title = $("title", xml);
    result = '&amp;lt;li class="channel" id="channel-'+title.attr("id")+'"&amp;gt;';
    result = result + '&amp;lt;div class="actions"&amp;gt;&amp;lt;a href="/tv/delete/'+title.attr("id")+'"&amp;gt;&amp;lt;img src="/media/tv/icon_deletelink.gif" alt="удалить"&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;';
    result = result + '&amp;lt;h2&amp;gt;&amp;lt;a href="/tv/'+title.attr("slug")+'"&amp;gt;'+title.text()+'&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';
    programs = $("program", xml);
    if (programs.size()&amp;gt;0) {
    result = result + '&amp;lt;ul&amp;gt;';
    programs.each(function() {
        result = result + "&amp;lt;li&amp;gt;&amp;lt;b&amp;gt;"+$(this).attr("time")+"&amp;lt;/b&amp;gt; "+$(this).text()+"&amp;lt;/li&amp;gt;";
    });
    result = result + '&amp;lt;/ul&amp;gt;';
    }
    else {
        result = result + "Нет телепрограмм"
    }
    result = result + "&amp;lt;/li&amp;gt;"
    $("#channelsList").append(result);
    checkBrowserWidth();
    $("#channelsList").sortable({change: newPlaces, hoverClass: "hover" });
    $("#addchannel").html('&amp;lt;a href="javascript:getNewChannels();" id="a_addchannel"&amp;gt;Добавить канал&amp;lt;/a&amp;gt;');
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Придётся забежать немного вперёд &lt;code&gt;sortableDestroy()&lt;/code&gt; это функция из jQuery UI, которая убирает возможность таскать элементы списка, &lt;code&gt;sortable()&lt;/code&gt; соответсвенно даёт эту возможность. Но в связи с особенностями реализации этой штуки при добавлении элемента в такой список, необходимо убирать "таскание" и снова его применять.
&lt;/p&gt;
&lt;p&gt;Ну вот, с добавлением канала без перезагрузки страницы разобрались. Удаление ещё проще. Его я даже не буду комментировать. Просто приведу код.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function del(id) {
    $("#channelsList").sortableDestroy();
    $.get('/tv/delete/'+id+'/?xhr');
    $("#channel-"+id).slideUp("slow", function() {
    $("#channel-"+id).remove();
    checkBrowserWidth();
    });
    $("#channelsList").sortable({change: newPlaces, hoverClass: "hover" });
}

@login_required
def deletechannel(request, item_id=None):
    setting = request.user.tv_Setting
    if request.POST:
        if request.POST.has_key('schannel'):
            for item_id in request.POST.getlist('schannel'):
                channel = get_object_or_404(Channel, id=int(item_id))
                place = get_object_or_404(setting.Channels, Channel=channel)
                setting.Channels.remove(place)
                place.delete()
    else:
        channel = get_object_or_404(Channel, id=item_id)
        place = get_object_or_404(setting.Channels, Channel=channel)
        setting.Channels.remove(place)
        place.delete()
        xhr = request.GET.has_key('xhr')
        if xhr:
            return HttpResponse("success")
    if request.GET.has_key("next"):
        return HttpResponseRedirect(request.GET['next'])
    return HttpResponseRedirect('/tv/')
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Далее по списку у нас возможность перетаскивания каналов по главной странице. По большому счёту оно уже таскается. Осталось только заставить его запоминать положение.
&lt;/p&gt;
&lt;p&gt;Как я уже говорил &lt;code&gt;sortable()&lt;/code&gt; реализует перетаскивание. Если же передать ей параметр change, с названием нашей callback функции, то мы сможем при любом изменении положения каналов сообщать об этом серверу. У меня это выглядит так:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$("#channelsList").sortable({change: newPlaces});
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Сама же функция newPlaces выглядит так:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function newPlaces() {
    checkBrowserWidth();
    result = "";
    $("#channelsList &amp;gt; li").each(function() {
        result=result+$(this).attr("id")+",";
    });
    $.get('/tv/changeplaces/?xhr', {'update': result});
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;То есть перебираем все элементы списка и их &lt;code&gt;id&lt;/code&gt; записываем в строку, которую отправляем серверу. Сервер эту строку успешно ловит, разбивает по запятой, проходится по всему получившимуся массиву и меняет &lt;code&gt;place.N&lt;/code&gt; (место в списке) на итеррационную переменную i. Полностью функция &lt;code&gt;changeplaces&lt;/code&gt; у меня получилась такой:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@login_required
def changeplaces(request):
    setting = request.user.tv_Setting
    if request.GET.has_key('up'):
        place = get_object_or_404(setting.Channels, Channel__id=request.GET['up'])
        place2 = get_object_or_404(setting.Channels, N=place.N-1)
        place.up()
        place2.down(setting.Channels.count())
    elif request.GET.has_key('down'):
        place = get_object_or_404(setting.Channels, Channel__id=request.GET['down'])
        place2 = get_object_or_404(setting.Channels, N=place.N+1)
        place.down(setting.Channels.count())
        place2.up()
    elif request.GET.has_key('update'):
        channels = request.GET['update'].split(",")
        i=0
        for channel in channels[:-2]:
            place = get_object_or_404(setting.Channels, Channel__id=int(channel[8:]))
            place.N = i
            place.save()
            i+=1
    if request.GET.has_key('xhr'):
        return HttpResponse("success")
    channels = []
    for place in setting.Channels.order_by('N'):
        channels.append(place.Channel)
    nchannels=[]
    for channel in Channel.objects.all():
        if not channel in channels:
            nchannels.append(channel)
    c = {
        "channels": setting.Channels.order_by('N'),
        "date": None,
        "display": setting.Mode,
        "user": request.user,
        "channel": None,
        "nchannels": nchannels,
    }
    return render_to_response('tv/changeplaces.html', c)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Если параметром передали &lt;code&gt;update&lt;/code&gt;, то выполняем то, что я сейчас как раз и описал. &lt;code&gt;up&lt;/code&gt; и &lt;code&gt;down&lt;/code&gt; нужны для изменения положения каналов через "Настройки". Кстати "Настройки" выглядят так:
&lt;/p&gt;
&lt;p&gt;&lt;a href="/media/blog/img/tvwatcher2.png"&gt;&lt;img src="/media/blog/img/tvwatcher2_trumb.png"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Функции &lt;code&gt;up&lt;/code&gt; и &lt;code&gt;down&lt;/code&gt; для &lt;code&gt;place&lt;/code&gt; определены прямо в модели и ничего интересного из себя не представляют:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def up(self):
    if self.N&amp;gt;0:
        self.N-=1
        self.save()
        return self.N
    else:
        return None
def down(self, all):
    if self.N&amp;lt;all:
        self.N+=1
        self.save()
        return self.N
    else:
        return None
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ну что? С перетаскиваем тоже разобрались? Надеюсь, что да.
&lt;/p&gt;
&lt;p&gt;Как сделать подгрузку описания фильма, я думаю все уже догадались. Если нет, смотрите код. Красявости понятие очень субъективное и стандартных эффектов вроде slideUp, а так же thickbox по моему скромному мнению вполне достаточно. Так что и этот пункт можно вычёркивать.
&lt;/p&gt;
&lt;p&gt;На этом пожалуй на сегодня всё. К следующему посту будет необходимо исправить кучу оставленных багов, а так же прикрутить какое-то внешнее api.
&lt;/p&gt;
&lt;p&gt;Проект как обычно можно забрать из svn:
   &lt;a href="http://tvwatcher.googlecode.com/svn/tags/post4"&gt;http://tvwatcher.googlecode.com/svn/tags/post4&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Ну и на закуску скрин с описание фильма:
&lt;/p&gt;
&lt;p&gt;&lt;a href="/media/blog/img/tvwatcher3.png"&gt;&lt;img src="/media/blog/img/tvwatcher3_trumb.png"&gt;&lt;/a&gt;
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/11/04/pishem-tv-programmu-na-django-chast-4/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/11/04/pishem-tv-programmu-na-django-chast-4/</feedburner:origLink></item><item><title>Обновление PR</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/1laGKbiED7Y/</link><description>
&lt;p&gt;Как уже всем известно, прошлой ночью был ап PageRank. Затронул он и этот блог PR подскочил с 0 до 2. Радостно. :)
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/10/27/obnovlenie-pr/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/10/27/obnovlenie-pr/</feedburner:origLink></item><item><title>Наконец-то!</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/Ux6PFOSh7Pc/</link><description>
&lt;p&gt;Наконец в Google Reader появился поиск!
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://cyxapeff.org/media/blog/img/greader-search.png" alt="Greader Search"/&gt;
&lt;/p&gt;
&lt;p&gt;Мега удобная вещь, давненько её ждал.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/09/06/nakonets-to/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/09/06/nakonets-to/</feedburner:origLink></item><item><title>Sape клиент</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/twnjBDmhBaI/</link><description>
&lt;p&gt;Написал тут на досуге &lt;a href="http://www.sape.ru/r.9d61809f91.php" title="Sape"&gt;Sape&lt;/a&gt;-клиент под мой телефон.
&lt;/p&gt;
&lt;p&gt;&lt;img src="/media/blog/img/sapeinfo.png" alt="Sape Info"/&gt;
&lt;/p&gt;
&lt;p&gt;Делает элементарные вещи, заходит на сайт и смотрит баланс. Показывает его Вам и сохраняет в базу данных. Затем можно эту статистику посмотреть. Когда нет доступа к компьютеру (в отпуске например) очень удобно.
&lt;/p&gt;
&lt;p&gt;Написан на python под symbian 7,8. Для запуска нужен сам &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=154155" title="Pys60"&gt;питон&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Исходный код доступен после установки в файле !:\System\Apps\SapeInfo\default.py (советую всем на всякий случай посмотреть и удостовериться, что программка никуда ваши логин\пароль не отсылает кроме как на саму сапу)
&lt;/p&gt;
&lt;p&gt;&lt;a href="/media/sape.sis" title="Скачать"&gt;Скачать sis пакет.&lt;/a&gt;
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/08/13/sape-klient/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/08/13/sape-klient/</feedburner:origLink></item><item><title>Новые фичи</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/5YL7_4rvLy4/</link><description>
&lt;p&gt;Прикрутил парочку новых фич к блогу.
   А именно:
   - Авторизацию по &lt;a href="http://the-notebook.org/10/01/2006/populyarno-ob-openid/" title="OpenId"&gt;OpenId&lt;/a&gt;. Вы можете 1 раз написать комментарий использую openid, после чего форум будет Вас "помнить". (до конца сессии) Имя берётся из hCard. (спасибо Maniac)
   - Rss лента комментариев к каждой статье.
   - Ну и кое-что подправил.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/08/10/novyie-fichi/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/08/10/novyie-fichi/</feedburner:origLink></item><item><title>Обзор программ для работы с iPod под Linux.</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/jUzs4TyMesM/</link><description>
&lt;p&gt;Когда я покупал свой iPod, то удостоверился, что есть возможность работать с ним из Linux.
&lt;/p&gt;
&lt;p&gt;И вот уже пол года использую gtkpod. Но не всё мне в нём нравится и я решил посмотреть что же ещё есть в линуксе для iPod'a. Всё действо будет происходить на моём компьютере с Debian Lenny, в качестве плеера iPod Nano Green 4Gb второго поколения.
&lt;/p&gt;
&lt;p&gt;Начну с того, что большинство медиа комбайнов под Linux поддерживают iPod в той или иной мере. Но существуют так же и специальные программки, предназначенные исключительно для iPod'a. Я не люблю сильно заморачиваться с софтом. Поэтому почти всегда ставлю софт только из репозитария дебиана. Поэтому почти весь рассмотренный здесь софт будет оттуда же. Я не углублялся в каждую программу отдельно, не искал плагины, не устанавливал какие-то дополнительные пакеты. Поэтому вполне возможно, что у какой-то программы интеграция с ipod'ом может быть гораздо лучше. (можете оставить свои комментарии и недовольства в комментариях)
&lt;/p&gt;
&lt;p&gt;Ну а теперь подробнее:
&lt;/p&gt;

&lt;h3&gt;Exaile Music Player&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/blog/img/exaile.png"&gt;&lt;img src="http://cyxapeff.org/media/blog/img/exaile_trum.png" alt="Exaile"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Этот плеер попытка создать клон амарока на gtk. Не буду сравнивать с амароком в качестве плеера. Сейчас меня интересует только его работа с iPod. Для того чтобы он "научился" работать с iPod нужно включить плагин "iPod Device Driver". После этого в главном окне появляется вкладка Devices. В ней выбираем iPod Device Driver. Упс. Не нашёлся наш айпод. Снова идём в плагины и указываем директорию куда он монтируется. Коннектимся. Появляется структура нашего айпода. Теперь мы можем слушать с него музыку, сделано довольно удобно. Отличий работы с коллекцией айпода от собственной коллекции нет. А вот плейлисты айпода по-крайней мере у меня работать отказались. Они отображаются слева в списочке, но открываться не хотят. Как добавлять туда музыку я не нашёл, окошко переноса музыки появляется, но как туда что-то добавить - не понятно...
   Вывод: поддержка айпода есть, но она сделана очень странно.
&lt;/p&gt;

&lt;h3&gt;Banshee&lt;/h3&gt;
&lt;p&gt;Ещё один плеер на gtk под Gnome.
   Запускаем. Подключаем айпод. Отлично. Тут же появился пункт IPOD. Переходим и... облом.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/blog/img/banshee_error.png"&gt;&lt;img src="http://cyxapeff.org/media/blog/img/banshee_error_trum.png" alt="Banshee"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;"Невозможно считать данные с вашего Ipod".
   Спросим "В чём причина этого?".
   Говорят, использован слишком новый iTunes. И Banshee не может понять базу, которую создал этот самый новый iTunes.
   И тут же предлагается 2 варианта решения:
   1) Подождать пока Banshee научится понимать эту базу.
   2) Повторно создать базу данных iPod.
&lt;/p&gt;
&lt;p&gt;Ладно попробуем пересоздать... Мда. Спасибо Banshee. Базу создал ты конечно создал, но прочитать русские названия был не в силах. При этом всё было в utf8 и ни один плеер никогда себе такого не позволял.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/blog/img/banshee_encoding.png"&gt;&lt;img src="http://cyxapeff.org/media/blog/img/banshee_encoding_trum.png" alt="Banshee"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Ладно глянем всё-таки что он ещё умеет. И так:
   Умеет показывать свойства айпода (имя устройства определил не правильно).
   Синхронизироваться с ним. Хотя как происходит синхронизация - не очень понятно. Но рисковать не стал. :)
   Импортировать из него музыку.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/blog/img/banshee_info.png"&gt;&lt;img src="http://cyxapeff.org/media/blog/img/banshee_info_trum.png" alt="Banshee"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Плюс сам Banshee умеет работать с подкастами соответственно и синхронизировать их должен смочь.
&lt;/p&gt;
&lt;p&gt;Как быстро переходить к артистам, альбомам не нашёл. Все песни отображаются в одном списке. Видимо необходимо использовать "поиск" и создавать "умные"плэйлисты.
&lt;/p&gt;
&lt;p&gt;Вывод: Если вы не слушаете русскую музыку и, то можно использовать.
&lt;/p&gt;

&lt;h3&gt;Rhythmbox&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/blog/img/Rhythmbox2.png"&gt;&lt;img src="http://cyxapeff.org/media/blog/img/Rhythmbox2_trum.png" alt="Rhythmbox"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Аналогично Banshee сам определил ipod. И показал его в левой колоночке.
   Переходим. Бросается в глаза, что поначалу всё в куче. Но тыкаем в обзор и появляется такая же панелькак как и у iTunes с исполнителями и альбомами. Плейлисты не доступны. Скопировать туда тоже что-либо не удалось. Включениеотключение плагина iPod ничего не меняет. Зачем он нужен - непонятно.
&lt;/p&gt;
&lt;p&gt;Вывод: Аналогично Exaile поддержка iPod только на уровне "послушать".
&lt;/p&gt;

&lt;h3&gt;Gtkpod&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/blog/img/gtkpod.png"&gt;&lt;img src="http://cyxapeff.org/media/blog/img/gtkpod_trum.png" alt="Gtkpod"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;В отличии от выше рассматриваемых программ это не музыкальный комбайн, а отдельная утилита для работы с iPod.
   Для начала необходимо указать куда подмонтирован айпод и его модель. После этого получаем к нему доступ. Есть панелька сортировки аля iTunes. Есть доступ к подкастам.
&lt;/p&gt;
&lt;p&gt;Ну а теперь о возможностях.
   Музыку можно слушать (через внешнюю утилиту, указывается в настройках)
   Песни можно удалять, редактировать им теги, импортировать на локальный компьютер.
   Добавлять музыку можно как через меню, так и Drug-and-Drop. Директориями и отдельными файлами. Есть возможность синхронизироваться с определённой директорией.
   Работа с плэйлистами.
   Синхронизация подкастов.
   Можно скробблить прослушанные треки в Last.fm
   Есть возможность синхронизировать контакты, записки, календарь (но только через внешние утилиты)
&lt;/p&gt;
&lt;p&gt;Вывод: Наверное лучшая программа под Linux для работы с iPod. Позволяет делать с музыкой и айподом всё что только можно. Но имхо, интерфейс у неё не очень удобный. + лично мне удобней когда всё находится в одном месте.
&lt;/p&gt;

&lt;h3&gt;Tripod&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/blog/img/tripod.png"&gt;&lt;img src="http://cyxapeff.org/media/blog/img/tripod_trum.png" alt="Tripod"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Первая утилита в обзоре на QT. Позволяет загружать фотографии на свой ipod. Программка очень странная. Она помимо просто загрузки фотографий позволяет создавать альбомы, но перемещать туда фотографии невозможно. Кнопкаtransfer для не дефолтного альбома недоступна.
   После того как я загрузил фотографии и зашёл в фототеку увидел: миниатюры некоторых фотографий отображаются 2 раза. Других же просто нет. (квадратик и в нём точка) Посмотреть картинку так же не удалось просто чёрный экран. После этого мойiPod завис и помогла только перезагрузка. Удалить им же фотографии не удалось.
&lt;/p&gt;
&lt;p&gt;Вывод: использовать только на свой страх и риск. А лучше вообще не использовать.
&lt;/p&gt;

&lt;h3&gt;Amarok&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/blog/img/amarok.png"&gt;&lt;img src="http://cyxapeff.org/media/blog/img/amarok_trum.png" alt="Amarok"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Очень популярный плеер под kde. Автоматически определить ipod он так же не сумел. (возможно в kde всё будет ok) Но спустя пору минут в разделе настройки и он становится виден. Умеет играть музыку прямо с айпода. Копировать её в свою коллекцию. Работать с плэйлистами.  Редактировать теги. Загружать музыку на iPod. Работать с подкастами. Сделано всё довольно удобно и просто.
&lt;/p&gt;
&lt;p&gt;Вывод: если бы он был на gtk, я бы сказал, что это лучшее решение в качестве музыкального проигрывателя+ipod. Kde'шники - ликуйте. :) Но мне он не подходит, поскольку всё окружение у меня на gtk.
&lt;/p&gt;

&lt;h3&gt;YamiPod.&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://cyxapeff.org/media/blog/img/yamipod.png"&gt;&lt;img src="http://cyxapeff.org/media/blog/img/yamipod_trum.png" alt="YamiPod"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Ещё одна утилитка предназначенная только для работы с ipod'ом.
   Огромный плюс этой утилиты её кроссплатформенность. Есть сборки и под винду и под линукс. Не требует какой бы то ни было установки. Её можно, например, кинуть на сам айпод и таскать с собой. Тогда на любом компьютере Вы без проблем сможете скопировать музыку в обоих направлениях. Автоматически нашла айпод, всё сделано довльно удобно и красиво.
   Умеет:
   - Играть
   - Импортировать
   - Экспортировать
   - Синхронизировать
   - Работать с заметками
   - Работать с плэйлистами
&lt;/p&gt;
&lt;p&gt;Но есть один бааальшой минус, который перечёркивает все плюсы. Она страшно тормозит. По-крайней мере у меня под линуксом.
&lt;/p&gt;
&lt;p&gt;Вывод: если у Вас оно не тормозит, то пожалуй будет одной из лучших программ для ipod.
&lt;/p&gt;

&lt;h3&gt;Заключение&lt;/h3&gt;
&lt;p&gt;Как видно, программ под Linux для работы с айподом великое множество. Если же Вам не понравилась ни одна из перечисленных здесь программ, вы можете поискать другие. Так же существуют библиотеки для работы с iPod (именно их использует большинство перечисленных здесь программ), благодаря этому вы можете написать свою идеальную программу не разбираясь в тонкостях работы плеера.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/08/03/obzor-programm-dlya-rabotyi-s-ipod-pod-linux/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/08/03/obzor-programm-dlya-rabotyi-s-ipod-pod-linux/</feedburner:origLink></item><item><title>Новый блог</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/_6VB5CbB0Oo/</link><description>
&lt;p&gt;Ну вот наконец сделал себе новый блог! Ну и конечно же зарегистрировал красивый домен.
&lt;/p&gt;
&lt;p&gt;Естественно, блог написан на джанго. А так как нормального (и дешёвого) shared хостинга с джанго нет, пришлось взять себе vds. Взял самый простой, да ещё и в США, так что скорость может не очень радовать.
&lt;/p&gt;
&lt;p&gt;Соответственно поменял мыло и адрес фида.
   Новые адрса:
   RSS: &lt;a href="http://feeds.cyxapeff.org/CyxapeffBlog"&gt;http://feeds.cyxapeff.org/CyxapeffBlog&lt;/a&gt;
   E-mail: max@cyxapeff.org
   Скорей всего джаббер тоже вскоре будет иметь красивый адрес. (использую службы google)
&lt;/p&gt;
&lt;p&gt;Движок особо не тестил, так что возможны всякие глюки и баги. :)
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/07/31/novyij-blog/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/07/31/novyij-blog/</feedburner:origLink></item><item><title>Мир Тесен</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/wDs0MiuFgE8/</link><description>
&lt;p&gt;Есть инвайты на &lt;a href="http://mirtesen.ru/"&gt;Мир Тесен&lt;/a&gt;. (&lt;a href="http://bbsod.com/2007/07/14/mir-tesen/"&gt;обзор&lt;/a&gt;)
&lt;/p&gt;
&lt;p&gt;Кому надо - обращайтесь.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/07/15/mir-tesen/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/07/15/mir-tesen/</feedburner:origLink></item><item><title>Пишем Tv программу на Django. Часть 3</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/wQ8XNJY38fo/</link><description>
&lt;p&gt;как обычно код этого поста тут: &lt;a href="http://tvwatcher.googlecode.com/svn/tags/post3"&gt;http://tvwatcher.googlecode.com/svn/tags/post3&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Наконец пришло время создать view. Вид. То, что будет видеть обычный пользователь когда зайдёт к нам на страничку.
&lt;/p&gt;
&lt;p&gt;В самом начале я задумывался о xml+xslt, но немножко подумав как это реализовывать пришёл к выводу, что в таком случае я потеряю очень мощный инструмент django. Его шаблоны. Поэтому будем делать на обыкновенном html4.
&lt;/p&gt;
&lt;p&gt;Первым делом я открываю Gimp и рисую макет будущей страницы... (чёрт, похоже я его уже потерял, вобщем поверьте на слово я его нарисовал)
&lt;/p&gt;
&lt;p&gt;Затем режу эту картинку и верстаю тестовую страничку. Привожу к виду как на картинке.
&lt;/p&gt;
&lt;p&gt;В результате оно стало выглядеть примерно так:
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bp3.blogger.com/_1kKtqQV8wNk/RnUEyJbcjVI/AAAAAAAAAJo/tZbwoWS5l50/s1600-h/Screenshot.png"&gt;&lt;img src="http://bp3.blogger.com/_1kKtqQV8wNk/RnUEyJbcjVI/AAAAAAAAAJo/tZbwoWS5l50/s320/Screenshot.png" alt="Preview"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;Да, не очень красиво. Особенно цвета. Ну да ладно...
&lt;/p&gt;
&lt;p&gt;Теперь нужно выделить основной код который будет повторяться на всех страницах. Это будет наш base.html, который мы закинем в ownproject/templates/tv/.
&lt;/p&gt;
&lt;p&gt;Если вы уже ознакомились с официальным туториалом, то знаете, что в шаблонах у джанго свой мини язык. Вот пользуясь им и создаём наш base.html
&lt;/p&gt;
&lt;p&gt;У меня получилась вот такая штука:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;{% block title %}Tv программа{% endblock %}&amp;lt;/title&amp;gt;
&amp;lt;script type="text/javascript" src="/media/tv/css.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;meta http-equiv="content-type" content="text/html; charset=UTF-8"&amp;gt;
&amp;lt;link href='/media/tv.css' type='text/css' rel='stylesheet'&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;div id="upperbar"&amp;gt;
    {% block upbar %}
    &amp;lt;div id="menu"&amp;gt;{% if user %}
            &amp;lt;a href=""&amp;gt;Настройки&amp;lt;/a&amp;gt; | &amp;lt;a href="/tv/logout/"&amp;gt;Выход&amp;lt;/a&amp;gt;
        {% else %}
            &amp;lt;a href="/tv/login/?next=/tv"&amp;gt;Войти&amp;lt;/a&amp;gt; |
            &amp;lt;a href="/tv/registration"&amp;gt;Регистрация&amp;lt;/a&amp;gt;
        {% endif %}&amp;lt;/div&amp;gt;
    &amp;lt;div id="hello"&amp;gt;Здравствуйте, {% if user %}
        {{ user.username }}!
        {% else %}
        Гость!
        {% endif %} | {% now "d F Y H:i" %}&amp;lt;/div&amp;gt;
    {% endblock %}
&amp;lt;/div&amp;gt;

&amp;lt;div id="upmain"&amp;gt;
    &amp;lt;h1 id="logo"&amp;gt;Tv программа&amp;lt;/h1&amp;gt;
&amp;lt;/div&amp;gt;

{% block week %}
    {% load menu_ex %}
    {% menu display date chanal %}
{% endblock %}

    {% block content %}{% endblock %}
&amp;lt;/div&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как видно в теге title написано {% block title %}Tv программа{% endblock %}. Это значит, что по умолчанию название страницы будет Tv программа, но мы можем его изменять в любом наследующем шаблоне, переопределив block title. То же самое происходит с upbar, week и content.
&lt;/p&gt;
&lt;p&gt;Так же на каждой странице будет отображаться верхний блок с днями недели и тп. Чтобы не таскать одно и то же из функции в функцию в view, я вынес их в отдельный шаблонный тег.
&lt;/p&gt;
&lt;p&gt;Для этого создаём папочку ownproject/tv/templatetags. В ней пустой файл __init__.py и menu_ex.py который собственно и является нашим тегом. Ничего особо интересного там нет. Так что кому интересно смотрим в svn. (вообще туда заглядывать просто обязательно! в самих постах очень многое пропущено) Единственно что стоит отметить, это то как сказать django что это именно тег. Делается это примерно так:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from django import template
register = template.Library()
def menu(display=0, date=None, chanal=None):
    ...
register.inclusion_tag('tv/menu.html')(menu)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Таблица стилей и яваскрипт не случайно положены в папку media. Дело в том, что встроенный веб сервер django не умеет просто так отдавать статику. Поэтому все картинки, js, css и тп обычно скидывается в какую-нибудь папку, например ownproject/media. Затем открывается ownproject/urls.py и дописывается такая строчка:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(r'^media/(?P.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В ownproject/settings.py определяем переменную MEDIA_ROOT. В моём случае:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MEDIA_ROOT = '/mnt/H/My Developement/django/mysite/media/'
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;И если директория была названа media, то &lt;strong&gt;необходимо&lt;/strong&gt; изменить ADMIN_MEDIA_PREFIX, например на amedia. (всё это в том же файле settings)
&lt;/p&gt;
&lt;p&gt;Ну вот. Теперь можно попробовать начать создавать нашу главную страницу.
   Создадим файл /ownproject/tv/urls.py и пропишем там:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from django.conf.urls.defaults import *
from django.conf import settings
from tv import views

urlpatterns = patterns('',
    (r'^$', views.index),
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Отлично. Теперь при попытке зайти на http://127.0.0.1:8000/tv будет вызываться функция index из ownproject/tv/views.py. Правда её ещё нет. :)
&lt;/p&gt;
&lt;p&gt;Займёмся её написанием... Хотя нет. Стоп! Что такое главная страница? Это телепрограмма на сегодня. То есть это то же самое, что и по ссылкам Пн, Вт, Ср, Чт и тд. Только дата устанавливается автоматически. Логично было бы написать функцию которая будет работать с любой датой, а в index просто вызывать её с сегодняшней датой. Этим и займёмся.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def index(request):
    return day(request, time.strftime("%Y-%m-%d"))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Нарисуем шаблон list.html, который будет выводить каналы.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def day(request, date):
    if request.user.is_authenticated(): # Проверяем авторизирован ли юзер
        user=request.user
        setting = user.tv_Setting
        display = tv_Setting.Mode # режим отображения берём из настроек
        chanals = []
        for place in setting.Chanals.order_by('N'): # Извлекаем из базы "места" сортираю по его номеру
            chanals.append(place.Chanal) # и добавляем в массив связанные с ними каналы
    else: # иначе юзер у нас None, а каналы просто первые четыре штуки
        user = None
        chanals = Chanal.objects.all()[:4]
        display = request.GET.has_key("allday") # режим отображание смотрим по тому есть ли в адресе переменная allday
    for chanal in chanals: # для каждого канала необходимо вызвать функцию get_chanal, чтобы добавить в них информацию из других таблиц
        chanal = get_chanal(display, date, chanal)
    c = { # именнованный массив который мы отдаём в шаблон
        "chanals": chanals,
        "date": date,
        "display": display,
        "user": user,
        "chanal": None,
    }
    return render_to_response('tv/list.html', c)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ну и посмотрим на ownproject/templates/tv/list.html. Там тоже ничего сложного:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{% extends "tv/base.html" %}
{% block content %}
    {% if user %}
        &amp;lt;div id="addchanal"&amp;gt;&amp;lt;a href="/tv/addchanals"&amp;gt;Добавить канал&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;
    {% endif %}
    {% if chanals %}
        {% for chanal in chanals %}
            &amp;lt;div class="chanal"&amp;gt;
                {% if user %}
                    &amp;lt;div class="actions"&amp;gt;&amp;lt;a href="/tv/delete/{{ chanal.id }}"&amp;gt;&amp;lt;img src="/media/tv/icon_deletelink.gif" alt="удалить"&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;
                {% endif %}
                {% if chanal.Icon %}
                &amp;lt;img src="{{ chanal.Icon }}"&amp;gt;
                {% endif %}
                &amp;lt;h2&amp;gt;&amp;lt;a href="/tv/{{ chanal.Slug }}"&amp;gt;{{ chanal.Title }}&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;
                &amp;lt;ul&amp;gt;
                    {% if chanal.programs %}
                        {% for program in chanal.programs %}
                        &amp;lt;li&amp;gt;{{ program.Time }}
                        {% if program.description %}
                            &amp;lt;a href="/tv/description/{{ program.description.id }}"&amp;gt;{{ program.Title }}&amp;lt;/a&amp;gt;
                        {% else %}
                            {{ program.Title }}
                        {% endif %}
                        &amp;lt;/li&amp;gt;
                        {% endfor %}
                    {% else %}
                        Нет телепрограмм
                    {% endif %}
                &amp;lt;/ul&amp;gt;
            &amp;lt;/div&amp;gt;
        {% endfor %}
    {% else %}
        Нет каналов.
    {% endif %}
    &amp;lt;script&amp;gt;
    checkBrowserWidth();
    &amp;lt;/script&amp;gt;
{% endblock %}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Говорим, что мы потомок base.html и переопределяем block content.
   Скрипт в конце необходим чтобы правельно выводить блоки с каналами.
   Здесь вообще довольно интересная история произошла. Изначально я нарисовал 2 колонки с каналами и каналы в своих колонках расположены один под другим. Вообщем получается как в той же бумажной телепрограмки. И вроде всё было хорошо, пока я не растянул свой браузер на всю ширину монитора (1280px). появилось просто ужасающее колличество свободного места. Тогда я все каналы сделал float:left, и стал выводить... Но конечно же получилось очень страшно, т.к у них у всех различная высота. Думал, думал, думал чего делать. Но так ничего лучше яваскрипта не придумал. Он смотрит на ширину окна браузера и в зависимости от него каждому Nому каналу ставит свойство clear: left. В результате получилось не совсем так как я хотел, но вроде более или менее нормально.
&lt;/p&gt;
&lt;p&gt;И так вернёмся к нашим баранам. Выделив функцию day, мы автоматически создали обработчик других дней. Поэтому дописываем в urls
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(r'^(?P\d{4}-\d{2}-\d{2})/$', views.day),
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Теперь можно перейти на сайт и потыкать по ссылкам. Оно должно работать. :)
&lt;/p&gt;
&lt;p&gt;Создание страничек с каждым каналом в отдельности и описанием тоже не представляют ничего интересного, поэтому на них можно посмотреть в svn. С добавлением\удалением канала у юзера то же самое. Поэтому и смотрим там же.
&lt;/p&gt;
&lt;p&gt;Теперь нужно к этому всему подключить пользователей. Как видно я уже учёл различное поведение для анонимного пользователя и авторизированного в виде и шаблонах. Поэтому осталось только сделать механизм входа\выхода\регистрации. Так как почти всё это в будующем будет заменено ajax'ом, то по возможности используем встроенные в django функции или элементарные формочки.
&lt;/p&gt;
&lt;p&gt;Для входа и выхода уже написаны полностью рабочие функции, осталось лишь прописать их в urls.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(r'^login/$', 'django.contrib.auth.views.login'),
(r'^logout/$', 'django.contrib.auth.views.logout'),
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;А вот регистрации готовой нет, поэтому набрасаем простенькую формочку в шаблоне.
   Django освобождает нас от необходимости прописывать бесмысленные функции в view, которые занимаются только тем, что рендерят шаблон. Вместо этого используем django.views.generic.simple.direct_to_template.
   В urls пропишем:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(r'^registration/$', 'django.views.generic.simple.direct_to_template', {'template': 'tv/registration.html'}),
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Форма после заполнения будет вызывать функцию createuser: (r'^createuser/$', views.createuser),
&lt;/p&gt;
&lt;p&gt;Она опять же элементарна. Почти всё за нас делает django. Импортируем User из django.contrib.auth.models и authenticate, login из django.contrib.auth.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;user = User.objects.create_user(request.POST['username'], '', request.POST['password']) # создаём пользователя
user.save() # сохраняем его
user = authenticate(username=request.POST['username'], password=request.POST['password']) 
login(request, user) # сразу же авторизируем
return HttpResponseRedirect('/tv/') # и кидаем на главную
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ну вот наверное и всё. В результате мы получили почти рабочий сайт с телепрограммой.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/06/17/pishem-tv-programmu-na-django-chast-3/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/06/17/pishem-tv-programmu-na-django-chast-3/</feedburner:origLink></item><item><title>SMF. Злость!</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/K_VCCfcCg8Y/</link><description>
&lt;p&gt;Спросите что такое SMF? Это &lt;a href="http://www.simplemachines.org/"&gt;Садо-Мазо Форум&lt;/a&gt;!
   Руки бы поотрывал его разработчикам. Ну как можно ТАК сделать систему шаблонов?! Код и хтмл вперемежку это просто какой-то кошмар. Но приходится продолжать мучить себя им, т.к нет ни одного вменяемого бесплатного форума с нормальной интеграцией в drupal... Хотя эту реализацию тоже довольно сложно назвать нормальной...
   Вот после знакомства с такими приложениями я понимаю, что просто обожаю django. Джанго как и весь питон заставляет писать правильно (чего стоят отступы питона или в джанго хочешь не хочешь, а приходится разделять модель, вид и шаблон).
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/05/20/smf-zlost/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/05/20/smf-zlost/</feedburner:origLink></item><item><title>Пишем Tv программу на Django. Часть 2</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/5oFW6d3HgHM/</link><description>
&lt;p&gt;Ну вот, модель мы &lt;a href="http://cyxapeff.org/blog/pishem-tv-programmu-na-django-chast-1/"&gt;создали&lt;/a&gt;. Таблицы создали. Теперь было бы их не плохо заполнить.
&lt;/p&gt;
&lt;p&gt;Заполнять будем парсером афиши@mail.ru Поэтому теперь мы будем злобными пиратами, ворующими чужой контент. Кому это не интересно можете пропускать эту запись сразу, а наполнять базу можно и какими-то легальными способами.
&lt;/p&gt;
&lt;p&gt;Мой способ - парсить майл.ру каждое воскресенье, доставая оттуда телепрограмму на следующую неделю. То есть сейчас необходимо написать какой-то скриптик, который потом нужно будет прописать в cron. И после этого мы всегда будем иметь актуальную информацию в нашей бд.
&lt;/p&gt;
&lt;p&gt;И так зайдём на &lt;a href="http://pda.tv.mail.ru"&gt;http://pda.tv.mail.ru&lt;/a&gt; и выберем какой-нибудь канал. Смотрим урл, например: &lt;a href="http://pda.tv.mail.ru/?gosetup=1&amp;amp;channel=365"&gt;http://pda.tv.mail.ru/?gosetup=1&amp;amp;channel=365&lt;/a&gt;. 365 это тот Num который мы создавали в модели. Но как видно отображаются лишь актуальные телепередачи, поэтому переключимся в вид "весь день". Но теперь отображается программа на сегодня, а нам бы нужно бы иметь возможность получать программу на разные дни. Выберем какой-нибудь другой день... Замечательно! Спасибо мэйлу, нам необходимо только циклом ходить по страничкам вида http://pda.tv.mail.ru/?date=[date]&amp;amp;gosetup=1&amp;amp;period=3&amp;amp;channel=[Num] и парсить их.
&lt;/p&gt;
&lt;p&gt;Посмотрим исходный код...
   Шикарно, ещё один респект мэйлу от меня.
   Нужная нам информация находится в блоке между &amp;lt;!-- START: Programm Content --&amp;gt; и &amp;lt;!-- END: Programm Content --&amp;gt;
   Там простая табличка, которую не составит большого труда отпарсить, тем более программы с описанием выделены тегом "b". Описание фильмов находится в теге "p" с классом t75. Ну вроде бы в устройстве сайта разобрались, Парсим!
&lt;/p&gt;
&lt;p&gt;Создаём новый файлик, я его назвал core.py Подключаем стандартные питоновские модули HTMLParser и urllib, ну и дальше по мануалу (хотя наверняка можно написать гораздо красивее):
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class ChanalHTMLParser(HTMLParser):
  """ Класс парсера для канала, создаём на основе HTMLParser """
  def __init__(self):
      HTMLParser.__init__(self)
      self.content=0 # несколько служебных переменных - переключателей
      self.flag=0
      self.result=[]
      self.buffer=[]
      self.flag2=0
  def handle_comment(self, data):
      """ Ищет в комментах необходимые строки """
      if "START: Programm Content" in data:
          self.content=1 # говорим что начались полезные данные
      elif "END: Programm Content" in data:
          self.content=0 # а теперь закончились

  def handle_starttag(self, tag, attrs):
      """ Функция вызывается при нахождении открывающего тега """
      if self.content==1: # Если мы внутри интересующий нас информации, то ищим в тегах
          if tag=="td":
              if len(attrs)&amp;gt;0:
                  if attrs[1][0]=="class" and attrs[1][1]=="time":
                      self.flag=1 # последующие данные, до закрытия тега будут временем
              else: # иначе ссылкой и названием программы
                  if self.flag==2: # конечно если тег со временем уже закрыт
                      self.flag=3 # говорим, что нашли строку с названием
          elif tag=="b" and self.flag==3: # встретили b - верный признак того, чтоо есть описание
              self.flag2=1 # сообщаем об этом
          elif tag=="a" and self.flag2==1 and self.flag==3: # а вот если встречаем a, то внутренность его нужна только если есть описание
              self.buffer.append(attrs[0][1]) # если всё ok, то добавляем ссылку в буффер

  def handle_data(self, data):
      """ Выполняется каждый раз когда оказывается 'внутри' тегов """
      if self.flag==1 or self.flag==3: # если там время или название
          self.buffer.append(data) # то добавляем их в буффер

  def handle_endtag(self, tag):
      """ Ну а эта функция соответсвенно проверяет закрывающие теги """
      if self.content==1: # снова делаем проверку
          if tag=="b":
              if self.flag2==1 and self.flag==3:
                  self.flag2=0 # обнуляем сообщение о описании
          if tag=="td":
              if self.flag==1: # если сейчас было 'время'
                  self.flag=2 # то сообщаем о том, что оно кончилось
              elif self.flag==3: # если было название
                  self.result.append(self.buffer) # до добавляем буфер к результату
                  self.buffer=[] # очищаем его
                  self.flag=0 # и обнуляем флаг
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;и
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class FilmHTMLParser(HTMLParser):
  """ Класс парсера для описаний, создаём на основе HTMLParser """
  content=0
  flag=0
  result=""
  def handle_comment(self, data):
      """ Ищем комменты """
      if "BEGIN: Main table" in data:
          self.content=1
      elif "END: Main table" in data:
          self.content=0

  def handle_starttag(self, tag, attrs):
      """ нужный тег с нужным классом """
      if self.content==1:
          if tag=="p":
              if len(attrs)==1:
                  if attrs[0][1]=="t75":
                      self.flag=1

  def handle_data(self, data):
      """ добавляем содержимое """
      if self.flag==1:
          self.result+=data

  def handle_endtag(self, tag):
      if self.content==1:
          if tag=="p":
              self.flag=0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Теперь скормив этим классам странички с программой или описанием будем получать только нужную информацию.
   делается это вот так:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;p = ChanalHTMLParser()
sock = urllib.urlopen("http://pda.tv.mail.ru/?date="+date+"&amp;amp;channel="+str(chanal.Num)+"&amp;amp;period=3")
htmlSource = sock.read()
htmlSource = unicode(htmlSource, "cp1251") # переводим страничку в юникод. Советую все данный поступающие от пользователя или ещё откуда-нибудь сразу же переводить в unicode. Меньше проблем будет.
sock.close()
p.feed(htmlSource)
print p.result
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Для описаний аналогично.
&lt;/p&gt;
&lt;p&gt;Это всё конечно замечательно, но надо это всё ещё и в бд запихнуть.
   Для этого нужно подключить к нашему скрипту django'вский ORM. Делается это довольно просто. А именно:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from django.core.management import setup_environ
sys.path.append("Путь до проекта") # т.к core.py у меня лежит в папке с приложением, которое обычно находится внутри папки проекта, то в место прямого пути я написал вот такую штукенцию os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
import settings
setup_environ(settings)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ну вот, теперь мы можем использовать всю мощь Django в своём скрипте.
   Подключаем из нашей недавно созданный модели классы каналы, программы и описания:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from mysite.tv.models import Chanal, Program, Description
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;для работы с бд я написал отдельный класс, хотя можно было обойтись и без этого:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class DataBase2:
  def get_chanals(self):
      """ Функция просто получает все каналы """
      chanals = Chanal.objects.all()
      return chanals

  def add_programm(self, chanal, ptime, title):
      """ Функция добавляет программу """
      if len(Program.objects.filter(Title=title, Time=ptime, Chanal=chanal))==0: # проверяем нет ли уже такой в бд
          p = Program(Title=title, Time=ptime, Chanal=chanal)
          p.save()
          return p
      else:
          return None

  def add_description(self, programm, content):
      """ Функция добавляет описание """
      if len(Description.objects.filter(Text=content, Program=programm))==0: # опять проверка на клонов
          Description(Text=content, Program=programm).save()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Вобщем-то всё. Осталось написать простой цикл обхода всех страниц и скрипт готов.
&lt;/p&gt;
&lt;p&gt;Взять его как всегда можно из &lt;a href="http://cyxapeff.blogspot.com/2007/05/tv-svn.html"&gt;моего svn&lt;/a&gt;:
   svn checkout http://tvwatcher.googlecode.com/svn/tags/post2/ tvwatcher
&lt;/p&gt;
&lt;p&gt;Запускаем django сервер, заходим в админку, добавляем какой-нибудь канал, указывая в Num номер канала на мэйле. Запускаем core.py с ключом w, снова идём в админку и видим, что добавились программы и описания этого канала на неделю.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/05/19/pishem-tv-programmu-na-django-chast-2/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/05/19/pishem-tv-programmu-na-django-chast-2/</feedburner:origLink></item><item><title>TV программа и svn</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/qB-2QsJOp9A/</link><description>
&lt;p&gt;Нужно как-то упорядочить код, я думаю.
   Поэтому последняя версия всегда будет лежать в http://tvwatcher.googlecode.com/svn/trunk/
   А исходный код который написан на момент написания каждого поста будет лежать в http://tvwatcher.googlecode.com/svn/tags/
&lt;/p&gt;
&lt;p&gt;Например исходный код первой части всегда будет доступен &lt;a href="http://tvwatcher.googlecode.com/svn/tags/post1/"&gt;отсюда&lt;/a&gt;
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/05/19/tv-programma-i-svn/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/05/19/tv-programma-i-svn/</feedburner:origLink></item><item><title>Пишем Tv программу на Django. Часть 1</title><link>http://feeds.cyxapeff.org/~r/CyxapeffBlog/~3/bACeEuyLrPM/</link><description>
&lt;p&gt;Ну вот блог создал. Чуть-чуть его покрутил, теперь и наполнять надо...
   А наполнять я его по крайней мере по началу буду рассказом о том как я создавал простенькое web приложение на django. В процессе я учусь сам и возможно, кому-то это тоже поможет.
&lt;/p&gt;
&lt;p&gt;Моим приложением будет Tv программа. Точнее не так, а web2.0Tv программа. :)
   Делаю я её в общем-то для себя и для моей не большой сети. Потому что на "внешке" всяких программ и так дополна. Тем не менее я попытаюсь написать тру приложение на django, xml+xlst (хотя в этом пока не уверен, может быть и обычным html'ем обойдусь), с ajax'ом, экспортом в разные форматы и тому подобной мишурой.
&lt;/p&gt;
&lt;p&gt;И так наверно приступим.
&lt;/p&gt;
&lt;p&gt;Для начала создаём проект:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;django-admin.py startproject mysite
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;создаём приложение:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd mysite
python manage.py startapp tv
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;сразу же подключаем его к проекту, для этого в settings.py в INSTALLED_APPS дописываем:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;'mysite.tv',
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;и настраиваем всё остальное, как Вам надо. Да не забудьте раскомментировать django.contrib.admin.
&lt;/p&gt;
&lt;p&gt;Отлично, теперь необходимо продумать и создать модель нашего приложения.
   Что необходимо Tv программе передач:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Каналы
 &lt;/li&gt;

 &lt;li&gt;
     Программы
 &lt;/li&gt;

 &lt;li&gt;
     Описание некоторых программ
 &lt;/li&gt;

 &lt;li&gt;
     И каким-то образом привязать это всё к пользователю.
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для каналов у меня получилась такая моделька:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Chanal(models.Model):
    """ Модель канала """
    class Admin: # Сразу же делаем их видимыми в админке
        list_display = ('Title',) # отображаем только названия
    def __str__(self): # вместа номера объекта будет возвращаться его название
        return self.Title
    Title = models.CharField(maxlength=50)
    Icon = models.ImageField(blank=True, upload_to="tv/images")
    Num = models.IntegerField(blank=True, null=True) # номер канала на сервере откуда его берём
    Slug = models.SlugField(maxlength=255, editable=False) # название канала в транслите, нужно для нормальных урлов
    def save(self):
        """ Функция, которая изменяет стандартный метод сохранения для нормального сохранения поля slug """
        self.Slug = slugify(self.Title.decode(settings.DEFAULT_CHARSET)) 
        super(Chanal, self).save()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Для программ:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Program(models.Model):
    class Admin: # аналогично делаем видимым в админке
        list_display = ('Title', 'Time', 'Chanal') # отображаем название, время и канал в 3 колонки
    def __str__(self):
        return self.Title
    Title = models.CharField(maxlength=150)
    Time = models.DateTimeField(blank=True)
    Chanal = models.ForeignKey(Chanal) # привязывает программу к каналу
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ну и наконец описание:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Description(models.Model):
    class Admin:
        list_display = ('Program', 'Text',)
    def __str__(self):
        return self.Text[:50]
    Text = models.TextField(blank=True)
    Program = models.ForeignKey(Program)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Теперь самое сложное. Нужно придумать как привязать это всю к пользователю. Для этого я создал класс setting. Он служит "мостиком" между пользователем и данными приложения.
&lt;/p&gt;
&lt;p&gt;Для связи этого класса с пользователем было бы логично написать что-то вроде:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Owner = models.ForeignKey(User)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Но тут появляется куча проблем. Где создавать этот класс? При регистрации пользователя? А если они уже есть, то придётся писать какой-то дополнительный скрипт. Короче мороки - куча. Очень красивое решение предложил Иван Сагалаев. У него даже целая статья этому посвящена, советую всем ознакомиться. Не долго думая, тупо копи-пастим его код. :) (как говориться сила OpenSource) После этого у нас появляется замечательное поле AutoOneToOneField. Теперь можно думать дальше. Сразу при планировании я решил, что каналы будут выводится блоками и соответственно было бы неплохо иметь возможность менять их местами. Думал как это сделать попроще довольно долго. Но ничего кроме как создать ещё один класс:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Place(models.Model):
    Chanal = models.ForeignKey(Chanal)
    N = models.IntegerField()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ничего придумать не смог. :( Если у кого есть идеи - поделитесь пожалуйста.
&lt;/p&gt;
&lt;p&gt;В результате для setting у меня получилось вот такая штука:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Setting(models.Model):
    # привязываем класс к пользователю... или наоборот... Не важно.
    Owner = AutoOneToOneField(User, related_name='tv_Setting')
    # Режим выводить все программы за день или только актуальные. То есть те, которые идут сейчас или начинаются позже
    Mode = models.CharField(maxlength=50)
    # Список каналов которые пользователь хочет видеть на главной странице c их номерами
    Chanals = models.ManyToManyField(Place)
    class Admin:
        pass # если в админке видить класс хотим, но ничего специфичного нет, можно как в туториале просто написать pass. Тогда будет выводится название объекта, который у нас подменяется именем пользователя.
    def __init__(self, *args, **kwargs):
        """ Функция вызывается при создании объекта. То есть когда пользователь первый раз обращается к нашему приложению. """
        super(Setting, self).__init__(*args, **kwargs)
        self.Mode = 'new' #  Устанавливаем режим в "только актуальные"
    def __str__(self):
        return str(self.Owner)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Всё что к этому времени написанно можно взять тут:
   svn checkout http://tvwatcher.googlecode.com/svn/tags/post1/ tvwatcher
   А последняя версия всегда будет доступна вот тут:
   svn checkout http://tvwatcher.googlecode.com/svn/trunk tvwatcher
&lt;/p&gt;
&lt;p&gt;(если хочется просто посмотреть на код, то можно прямо браузером перейти по этим ссылкам и посмотреть)
&lt;/p&gt;
&lt;p&gt;Теперь в urls.py раскомментируем строчку
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(r'^admin/', include('django.contrib.admin.urls')),
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Выполняем в консоли:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python manage.py syncdb
python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Теперь по адресу http://127.0.0.1:8000/admin/ у вас лежит рабочая админка. Туда можно зайти и убедиться, что все наши классы правильно создались.
&lt;/p&gt;
&lt;p&gt;На этом пока всё. В следующей части займёмся наполнением базы данных.
&lt;/p&gt;
&lt;p&gt;P.S чуть не забыл. Я использую сторонний модуль pytils от Pythy. Просто закиньте модуль в директорию с проектом. После этого будет работать import.
&lt;/p&gt;
</description><guid isPermaLink="false">http://cyxapeff.org/blog/2007/05/18/pishem-tv-programmu-na-django-chast-1/</guid><feedburner:origLink>http://cyxapeff.org/blog/2007/05/18/pishem-tv-programmu-na-django-chast-1/</feedburner:origLink></item></channel></rss>
