<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>solshark: акула Соляриса &#187; django</title>
	<atom:link href="http://solshark.i-seo.biz/category/django/feed/" rel="self" type="application/rss+xml" />
	<link>http://solshark.i-seo.biz</link>
	<description>Это был странный лес - сначала я ходил за грибами, потом они за мной...</description>
	<lastBuildDate>Sat, 10 Apr 2010 19:59:27 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>django debug toolbar</title>
		<link>http://solshark.i-seo.biz/2008/12/25/django-debug-toolbar/</link>
		<comments>http://solshark.i-seo.biz/2008/12/25/django-debug-toolbar/#comments</comments>
		<pubDate>Wed, 24 Dec 2008 21:27:25 +0000</pubDate>
		<dc:creator>solshark</dc:creator>
				<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://solshark.i-seo.biz/?p=417</guid>
		<description><![CDATA[Всем, кто использует django - потрясающая новость. Сегодня мой коллега откопал в недрах тырнета потрясающую штуку. Тулбар для джангистов. Показывает кучу полезной информации (request, response, headers, sql запросы). Всячески рекомендую.
 http://github.com/robhudson/django-debug-toolbar/tree/master
]]></description>
			<content:encoded><![CDATA[<p>Всем, кто использует django - потрясающая новость. Сегодня <a href="http://infinity9.org.ua/">мой коллега</a> откопал в недрах тырнета потрясающую штуку. Тулбар для джангистов. Показывает кучу полезной информации (request, response, headers, sql запросы). Всячески рекомендую.</p>
<p><a href="http://github.com/robhudson/django-debug-toolbar/tree/master"> http://github.com/robhudson/django-debug-toolbar/tree/master</a></p>
]]></content:encoded>
			<wfw:commentRss>http://solshark.i-seo.biz/2008/12/25/django-debug-toolbar/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>django : отображение древовидных данных</title>
		<link>http://solshark.i-seo.biz/2008/08/23/django-otobrazhenie-drevovidnyx-dannyx/</link>
		<comments>http://solshark.i-seo.biz/2008/08/23/django-otobrazhenie-drevovidnyx-dannyx/#comments</comments>
		<pubDate>Sat, 23 Aug 2008 13:46:36 +0000</pubDate>
		<dc:creator>solshark</dc:creator>
				<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://solshark.i-seo.biz/?p=24</guid>
		<description><![CDATA[Столкнулся с необходимостью вывести дерево элементов (список категорий с подкатегориями). Глубина вложенности изначально не ограниченна. Решение задачи дальше.
Древовидные данные
Итак, есть модель:
class Category(models.Model):
    master = models.ForeignKey('self',related_name='translations',null=True,blank=True)
    title = models.CharField(max_length=250)
    parent = models.ForeignKey('self',blank=True,null=True)
    description = models.TextField()
    cdate = models.DateTimeField(auto_now_add=True)
    [...]]]></description>
			<content:encoded><![CDATA[<p>Столкнулся с необходимостью вывести дерево элементов (список категорий с подкатегориями). Глубина вложенности изначально не ограниченна. Решение задачи дальше.<span id="more-24"></span></p>
<h3>Древовидные данные</h3>
<p>Итак, есть модель:</p>
<pre><code class="python">class Category(models.Model):
    master = models.ForeignKey('self',related_name='translations',null=True,blank=True)
    title = models.CharField(max_length=250)
    parent = models.ForeignKey('self',blank=True,null=True)
    description = models.TextField()
    cdate = models.DateTimeField(auto_now_add=True)
    mdate = models.DateTimeField(auto_now=True)
    language = models.CharField(max_length=2, choices=settings.LANGUAGES)
    def __unicode__(self):
        return self.title</code></pre>
<p>Как видно, поле <strong>parent</strong> позволяет указать родителя и таким образом создать вложения неограниченной глубины.</p>
<p>Теперь возникает вопрос - как в <strong>шаблоне</strong> организовать <strong>рекурсивный вывод данных</strong>. Я пропущу все прелюдии и ошибочные пути, которыми я шел, такие как get_levels_count(), get_level_n(n) и т.п. В конечном итоге нужную функциональность удалось организовать при помощи шаблонных тегов.</p>
<h3>Шаблонный тег для рекурсивного вывода данных</h3>
<p>Начнем писать свой тег.</p>
<p>1. В папке своего приложения создаем папку <strong>templatetags</strong>, в ней создаем пустой файл <strong>__init__.py</strong> и файл <strong>category_tree.py</strong>. В последнем собственно и будет наш тег.</p>
<p>2. В файл category_tree.py вписываем следующее:</p>
<pre><code class="python">from django import template
from shop.products.models import Category

register = template.Library()

@register.inclusion_tag('products/templatetags/category_tree.html')
def category_tree(context,category):
    children = Category.objects.filter(parent=category)
    return {'category': category, 'children' : children,}</code></pre>
<p>3. В шаблон <strong>products/templatetags/category_tree.html</strong> пишем следующее:<br />
<code> </code></p>
<pre>{% load category_tree %}
&lt;li&gt;{{ category.title }}
&lt;ul&gt;
    {% for child in children %}
	&lt;li&gt;{% category_tree child %}&lt;/li&gt;
    {% endfor %}
&lt;/ul&gt;
&lt;/li&gt;</pre>
<p>4. Ну и наконец, в главный шаблон, в котором нужно вывести дерево:</p>
<pre>{% load category_tree %}
    &lt;ul&gt;
    {% for category in categories %}
	&lt;li&gt;{% category_tree category %}&lt;/li&gt;
    {% endfor %}
    &lt;/ul&gt;</pre>
<p>Собственно, это все. Виват, <strong>django</strong>!</p>
]]></content:encoded>
			<wfw:commentRss>http://solshark.i-seo.biz/2008/08/23/django-otobrazhenie-drevovidnyx-dannyx/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>django &#8211; все сломалось после обновления</title>
		<link>http://solshark.i-seo.biz/2008/07/21/django-vse-slomalos-posle-obnovlenia/</link>
		<comments>http://solshark.i-seo.biz/2008/07/21/django-vse-slomalos-posle-obnovlenia/#comments</comments>
		<pubDate>Mon, 21 Jul 2008 13:39:23 +0000</pubDate>
		<dc:creator>solshark</dc:creator>
				<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://solshark.i-seo.biz/?p=21</guid>
		<description><![CDATA[Обновив в очередной раз django из svn, при попытке зайти в админку увидел неприятное сообщение:
ImproperlyConfigured: Error while importing URLconf 'django.contrib.admin.urls': No module named urls
Немного погуглив, решение было найдено. Как оказалось позже, это только начало...

Причины
Итак, причина этой ошибки, как и многих других - в trunk наконец-то влили бранч newforms-admin. Кроме того, попутно поменяли кучу всего нужного [...]]]></description>
			<content:encoded><![CDATA[<p>Обновив в очередной раз <strong>django</strong> из <strong>svn</strong>, при попытке зайти в <strong>админку</strong> увидел неприятное сообщение:</p>
<pre>ImproperlyConfigured: Error while importing URLconf 'django.contrib.admin.urls': No module named urls</pre>
<p>Немного погуглив, решение было найдено. Как оказалось позже, это только начало...</p>
<p><span id="more-21"></span></p>
<h2>Причины</h2>
<p>Итак, причина этой ошибки, как и многих других - в <strong>trunk</strong> наконец-то влили бранч <strong>newforms-admin</strong>. Кроме того, попутно поменяли кучу всего нужного и полезного. Итак, решаем наши проблемы.</p>
<h2>Ошибка при доступе к админ-части.</h2>
<p>Связана с изменением синтаксиса URLconf. Если раньше у вас в конфиге было что-то вроде</p>
<pre>from django.conf.urls.defaults import *
urlpatterns = patterns('',
    (r'^admin/', include('django.contrib.admin.urls')),
)
</pre>
<p>то теперь нужно сделать так:</p>
<pre>from django.conf.urls.defaults import *
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',
    (r'^admin/(.*)', admin.site.root),
)</pre>
<h2>Управление моделями</h2>
<p>Казалось бы, все пучком, админка ожила, но... В новооживленной админке не оказалось моих моделей. Опять же, гугл... И тут я нашел бесценную страницу (ссылка ниже) на которой было описание всех моих мытарств. В общем, новое изменение - теперь вместо</p>
<pre>class MyModel(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    slug = models.CharField(max_length=60, prepopulate_from=('first_name', 'last_name'))

    class Admin:
        pass
</pre>
<p>все, кому не чуждо django, пишут так:</p>
<pre>class MyModel(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    slug = models.CharField(max_length=60)

from django.contrib import admin

admin.site.register(MyModel)
</pre>
<p>В общем, вот так вот. Django - очень динамичный фреймворк. Быстро развивается, в связи с чем и случаются иногда некоторые сюрпризы. Впрочем, аргументов в пользу django и тут хватает. <strong>trunk</strong> он на то и trunk чтобы менятся. Стабильные версии стабильны <img src='http://solshark.i-seo.biz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Ну и разработчики честно предупредили о том, что всем будут ласты т.к. джанго растет и развивается. И, наконец, главный плюс в данных обстоятельствах - тот самый <a href="http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges">супердокумент</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://solshark.i-seo.biz/2008/07/21/django-vse-slomalos-posle-obnovlenia/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>django + openid: сервер своими руками (часть 1).</title>
		<link>http://solshark.i-seo.biz/2008/07/14/django-openid-server-svoimi-rukami-1/</link>
		<comments>http://solshark.i-seo.biz/2008/07/14/django-openid-server-svoimi-rukami-1/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 14:39:12 +0000</pubDate>
		<dc:creator>solshark</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://solshark.i-seo.biz/?p=19</guid>
		<description><![CDATA[Под влиянием самого известного джангиста в рунете, а теперь и по совместительству агитатора за OpenID, я решил завести и себе эту модную фишку. В смысле, обзавестись OpenID. Как сторонник теории заговора (и владелец мыла в google.com, вот ведь парадокс) я решил поднимать OpenID-server у себя. Враги не должны знать куда я хожу. Ну и все [...]]]></description>
			<content:encoded><![CDATA[<p>Под влиянием самого известного джангиста в рунете, а теперь и по совместительству <a title="Иван за OpenID :)" href="http://softwaremaniacs.org/blog/2007/04/24/thinking-of-being-openid-server/">агитатора за OpenID</a>, я решил завести и себе эту модную фишку. В смысле, обзавестись <strong>OpenID</strong>. Как сторонник теории заговора (и владелец мыла в google.com, вот ведь парадокс) я решил поднимать OpenID-server у себя. Враги не должны знать куда я хожу. Ну и все такое. Ну и поскольку <strong>Django</strong> - полный рулез, буду делать все это на базе <strong>Django</strong>. Что из этого получается - смотрим (или читаем).</p>
<p><span id="more-19"></span></p>
<h2>Компоненты:</h2>
<ul>
<li>собственно, Django (svn trunk)</li>
<li>библиотека <a href="http://openidenabled.com/python-openid/">python-openid</a> (я взял версию 2.2.1)</li>
<li>apache, vim, mod_python 3.3.1 <img src='http://solshark.i-seo.biz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<p>Путем предварительного гугления было найдено такое решение: <a title="DjangoID" href="http://trac.nicolast.be/djangoid">DjangoID</a>. Теоретически, это уже готовая реализация сервера и клиента. Но, насколько я понял, проект заброшен. Во всяком случае последним коммитам около двух лет. И потом, я хотел бы попробовать максимально "с ноля", чтобы разобраться что, почем, где и зачем. Поэтому использовать <strong>DjangoID</strong> не будем, будем пробовать сами (настолько сами, насколько получится).</p>
<h2>Подготовка</h2>
<p>Думаю, базовое окружение у вас уже готово и настроено. Т.е. Django работает. Проект, в который я буду всю эту петрушку интегрировать, называется <strong>labs</strong>. Так что будьте внимательны при копипасте <img src='http://solshark.i-seo.biz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Установим библиотеку <strong>python-openid</strong>, которая будет реализовывать основной функционал сервера (ну и клиента в дальнейшем). Я выбрал самый простой путь:</p>
<pre>easy_install -v python-openid</pre>
<p>Библиотека установлена. Едем дальше. Качаем себе дистрибутив библиотеки (ссылка выше). Зачем? Там папка есть полезная, examples. Она нам пригодится. Распаковываем. Находим папку <strong>examples</strong>. В ней лежит <strong>djopenid</strong>. Нам туда. Оппа - да тут же полноценный Django-проект. Хмм. Интересно. Можно попробовать запустить. Но я не стал. Мне проект не нужен. Я хочу приложение. Отдельное такое себе <strong>openidserver</strong>, чтобы интегрировать его в свой проект. Вопрос о рациональности пока отложим - может быть и стоит сделать отдельный проект, но я хочу приложение. Значится, копируем папку <strong>server</strong> в свой проект. Я сразу переименовал эту папку в openidserver, для наглядности. Файлик <strong>util.py</strong> из корня демор-проекта копируем в <strong>openidserver</strong> - не люблю мусора в корне проекта. Ну и не забываем про папку templates. Из библиотеки копируем в свой склад шаблонов. Опять же, я перенес всю петрушку в <strong>templates/openidserver/</strong>. Итак, структура проекта выглядит следующим образом:</p>
<pre>labs
    -openidserver</pre>
<pre>        --models.py, views.py, urls.py, util.py, tests.py, __init__.py
    -templates
        -openidserver
            --index.html, xrds.xml
            -core
                 --endpoint.html,idPage.html,index.html,trust.html
</pre>
<h2>Начинаем настройки:</h2>
<p>Первым делом добавлем новое приложение в setting.py:</p>
<pre>INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'labs.openidserver',
)</pre>
<p>В корневой файл urls.py добавляем информацию про новые адреса:</p>
<pre>  ('^server/', include('labs.openidserver.urls')),</pre>
<p>Отрываем файл openidserver/ursl.py и редактируем: '<strong>djopenid</strong>.server.views' -&gt; '<strong>labs</strong>.openidserver.views'.</p>
<p>Следующий файл, который необходимо отредактировать: <strong>openidserver/views.py</strong>. В нем нужно поменять названия модулей, из которых импортируются функции:</p>
<p>Было:</p>
<pre>from djopenid import util
from djopenid.util import getViewURL</pre>
<p>Стало:</p>
<pre>from labs.openidserver import util
from labs.openidserver.util import getViewURL</pre>
<p>Так, теперь теоретически можно пробовать. Пробуем открыть адрес http://domainname.com/server ...</p>
<p>Оппа. Неприятнейшая ошибка:</p>
<h4>TypeError at /server/</h4>
<h5>unsupported operand type(s) for +: 'NoneType' and 'str'</h5>
<p>Смотрим на источник ошибки: labs/openidserver/util.py in getViewURL, line 90</p>
<p>Видим такую вот неприятную функцию в файле <strong>util.py</strong>:</p>
<pre>88 def getViewURL(req, view_name_or_obj, args=None, kwargs=None):
89     relative_url = reverseURL(view_name_or_obj, args=args, kwargs=kwargs)
90     full_path = req.META.get('SCRIPT_NAME', '') + relative_url
91     return urljoin(getBaseURL(req), full_path)</pre>
<p>Понимаем, что проблема в  META['SCRIPT_NAME']. Гуглим. Находим вот такой вот <a title="Проблема с переменной окружения SCRIPT_NAME" href="http://code.djangoproject.com/ticket/1516">тикет</a>. Еще гуглим. Изучаем, откуда ноги растут у этого бага. Скорее всего, окуда-то из mod_python. Огорчаемся. Мысленно взываем к <a title="Иван - гуру в области Django" href="http://softwaremaniacs.org/about/">Ивану</a> и просим его рассказать как это пофиксить. А пока Иван молчит, делаем такой вот грязный хак:</p>
<pre>88 def getViewURL(req, view_name_or_obj, args=None, kwargs=None):
89     relative_url = reverseURL(view_name_or_obj, args=args, kwargs=kwargs)
90     full_path = 'http://domainname.com' + relative_url
91 #    full_path = req.META.get('SCRIPT_NAME', '') + relative_url
92     return urljoin(getBaseURL(req), full_path)
</pre>
<p><em><strong>ВНИМАНИЕ:</strong> прошу в этом месте критиков задержать дыхание и не писать что это уродство потому что... Я до конца со всей этой кухней еще не разобрался, поэтому пока не знаю где это вылезет и не придумал как обойти. Конструктив приветствуется.</em></p>
<p>Так, редактируем, сохраняем, пробуем еще раз. Снова ошибка, но в этот раз уже проще:</p>
<h5>TemplateDoesNotExist at /server/</h5>
<h6>server/index.html</h6>
<p>Вспоминаем, что поменяли название папки с шаблонами. Надо править пути. Благо, файл и строка известны. Правим. Не забываем, что в некоторых файлах шаблонов есть блоки  <strong>{% extends "..." %}</strong>. Их правим тоже. <em>Прим.: ниже ссылка на архив с уже отредактированными файлами, если лениво руками править.</em></p>
<p>Итак, пробуем еще раз. Ухты! Работает:</p>
<div class="box">This is an example server built for the Django framework.  It only     authenticates one OpenID, which is also served by this     application.  The OpenID it serves is</p>
<pre><a href="http://labs.i-seo.biz/server/user/">http://domainname.com/server/user/</a></pre>
</div>
<p>Собственно, цель первой части данного цикла достигнута - запустить хоть что-то, похожее на <strong>сервер OpenID</strong>. Но для очистки совести, чтобы убедится, что наше деяние имеет признаки OpenID, переходим <a title="Проверка OpenID сервера." href="http://openidenabled.com/resources/openid-test/diagnose-server/">сюда</a>.</p>
<p>Вводим адрес своего сервера, http://domainname.com/server/user, нажимаем Check и... о чудо: <span class="event">Associate (DH-SHA1 session) - Success!</span></p>
<p>Значит, все-таки что-то там завелось <img src='http://solshark.i-seo.biz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   В следующей части будем персонализировать наше детище.</p>
<p>А пока, для тех, кому лень редактировать файлы и править пути к шаблонам, <a title="OpenID server - django application - source code" href="http://solshark.i-seo.biz/openidserver.tar.bz2">архив с кодом</a> приложения для простого OpenID сервера.</p>
]]></content:encoded>
			<wfw:commentRss>http://solshark.i-seo.biz/2008/07/14/django-openid-server-svoimi-rukami-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

