<?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/"
	>

<channel>
	<title>Marcin Kaszyński &#187; Python</title>
	<atom:link href="http://marcinkaszynski.com/blog/index.php/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://marcinkaszynski.com/blog</link>
	<description>Firmy i projekty programistyczne</description>
	<pubDate>Fri, 06 Nov 2009 17:13:54 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Warsztaty IT: nowe kursy</title>
		<link>http://marcinkaszynski.com/blog/index.php/2009/02/11/warsztaty-it-nowe-kursy/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2009/02/11/warsztaty-it-nowe-kursy/#comments</comments>
		<pubDate>Wed, 11 Feb 2009 03:22:03 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Python]]></category>

		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://marcinkaszynski.com/blog/?p=272</guid>
		<description><![CDATA["Warsztaty Django dowodzą, że formuła zajęć się sprawdza, więc co można teraz zrobić? Nowe, ciekawe kursy :)" &#8211; właśnie dodałem do stronie Warsztatów IT zapowiedź nowych szkoleń: Ruby on Rails i&#160;programowania w&#160;Pythonie.
A przy okazji &#8211; do najbliższych warsztatów Django już niecałe dwa tygodnie, miejsc systematycznie ubywa.  Więcej szczegółów tutaj, a&#160;jeśli chcesz mieć pewność że [...]]]></description>
			<content:encoded><![CDATA[<p>"Warsztaty Django dowodzą, że formuła zajęć się sprawdza, więc co można teraz zrobić? Nowe, ciekawe kursy :)" &ndash; właśnie dodałem do stronie <a href="http://warsztatyit.pl/">Warsztatów IT</a> <a href="http://warsztatyit.pl/2009/02/nowe-kursy/">zapowiedź</a> nowych szkoleń: Ruby on Rails i&nbsp;programowania w&nbsp;Pythonie.</p>
<p>A przy okazji &ndash; do najbliższych warsztatów Django już niecałe dwa tygodnie, miejsc systematycznie ubywa.  Więcej szczegółów <a href="http://warsztatyit.pl/django/">tutaj</a>, a&nbsp;jeśli chcesz mieć pewność że weźmiesz udział &ndash; <a href="http://warsztatyit.pl/django/rejestracja-200902/">zapisz się już dzisiaj</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2009/02/11/warsztaty-it-nowe-kursy/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Django a&#160;martwe drzewa</title>
		<link>http://marcinkaszynski.com/blog/index.php/2009/01/16/django-a-martwe-drzewa/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2009/01/16/django-a-martwe-drzewa/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 13:41:53 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Programowanie]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://marcinkaszynski.com/blog/?p=254</guid>
		<description><![CDATA[Po ostatnich warsztatach dostałem pytanie o&#160;książki na temat Django.  Odpowiedź może być interesująca dla większej grupy ludzi, więc wklejam ją także tutaj.
Z książkami, niestety, jest marnie.  Głównie dlatego, że przed wydaniem wersji 1.0 Django mocno się zmieniało.
Po polsku nie pojawiło się chyba jeszcze nic, chociaż od dłuższego czasu Helion ma "w przygotowaniu" Django. [...]]]></description>
			<content:encoded><![CDATA[<p>Po ostatnich <a href="http://warsztatyit.pl/django/">warsztatach</a> dostałem pytanie o&nbsp;książki na temat Django.  Odpowiedź może być interesująca dla większej grupy ludzi, więc wklejam ją także tutaj.</p>
<p>Z książkami, niestety, jest marnie.  Głównie dlatego, że przed wydaniem wersji 1.0 Django mocno się zmieniało.</p>
<p>Po polsku nie pojawiło się chyba jeszcze nic, chociaż od dłuższego czasu Helion ma "w przygotowaniu" <a href="http://helion.pl/ksiazki/cwdjan.htm">Django. Ćwiczenia praktyczne</a>.</p>
<p>Po angielsku jest <a href="http://djangobook.com/">The Django Book</a>.  Zostało wydane przez Apress, ale w&nbsp;wersji opisującej 0.96, różnic niestety jest dużo i&nbsp;to w&nbsp;ważnych miejscach: szablony, interfejs administracyjny, obsługa formularzy.  Wersja dla 1.0 właśnie powstaje (fragment już można przeczytać na stronie) i&nbsp;jest spora szansa, że będzie aktualna dość długo, bo głównym powodem tak dużych zmian w&nbsp;ostatniej chwili była chęć ustabilizowania API.  <em>Jeśli czyta to ktoś z&nbsp;jakiegoś wydawnictwa: tak, to jest dobry moment żeby pomyśleć nad tłumaczeniem.</em></p>
<p>Więc niestety dobrej odpowiedzi nie mam.  ALE Django ma naprawdę dobrze napisaną i&nbsp;aktualną <a href="http://docs.djangoproject.com">dokumentację</a> (bardzo o&nbsp;to dbają &ndash; praktycznie każdy commit zmieniający cokolwiek widocznego dla użytkownika zawiera też odpowiednią zmianę w&nbsp;docach), więc na razie RTFM jest najlepszym rozwiązaniem <img src='http://marcinkaszynski.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2009/01/16/django-a-martwe-drzewa/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Warsztaty Django: druga edycja</title>
		<link>http://marcinkaszynski.com/blog/index.php/2008/12/10/warsztaty-django-druga-edycja/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2008/12/10/warsztaty-django-druga-edycja/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 13:50:32 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.elksoft.pl/index.php/2008/12/10/warsztaty-django-druga-edycja/</guid>
		<description><![CDATA[Od kilku dni można zapisywać się na drugą edycję warsztatów "Tworzenie aplikacji w&#160;Django".  Dla tych, którzy jeszcze zastanawiają się, czy warto, umieściłem na stronie opinie nadesłane przez uczestników pierwszej, listopadowej.  Między innymi taką:
Pierwszy raz uczestniczyłem w&#160;warsztatach, podczas których uczestnicy nie mieli ochoty wychodzić na przerwy.
- Marcin Raczyński

Kiedy ostatnio byliście na szkoleniu, którego uczestnicy [...]]]></description>
			<content:encoded><![CDATA[<p>Od kilku dni można zapisywać się na drugą edycję warsztatów "Tworzenie aplikacji w&nbsp;Django".  Dla tych, którzy jeszcze zastanawiają się, czy warto, umieściłem <a href="http://warsztatyit.pl/django/">na stronie</a> opinie nadesłane przez uczestników pierwszej, listopadowej.  Między innymi taką:</p>
<blockquote><p>Pierwszy raz uczestniczyłem w&nbsp;warsztatach, podczas których uczestnicy nie mieli ochoty wychodzić na przerwy.</p>
<p>- Marcin Raczyński
</p></blockquote>
<p>Kiedy ostatnio byliście na szkoleniu, którego uczestnicy żałowali że już się skończyło i&nbsp;od razu pytali o&nbsp;kontynuację? <img src='http://marcinkaszynski.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Najbliższą szansę macie już 13 stycznia.  Warto <a href="http://warsztatyit.pl/django/rejestracja-200901/">zapisać się</a> już dzisiaj, bo z&nbsp;dwunastu miejsc pierwsze trzy są już zarezerwowane.  Dodatkowo, zostało już tylko 10 dni na skorzystanie ze&nbsp;zniżki.</p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2008/12/10/warsztaty-django-druga-edycja/feed/</wfw:commentRss>
		</item>
		<item>
		<title>I po warsztatach</title>
		<link>http://marcinkaszynski.com/blog/index.php/2008/11/28/i-po-warsztatach/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2008/11/28/i-po-warsztatach/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 16:44:19 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.elksoft.pl/index.php/2008/11/28/i-po-warsztatach/</guid>
		<description><![CDATA[Ogólne podsumowanie umieściłem we&#160;wpisie na stronie Warsztatów IT.  Tutaj dodam, że:

przede wszystkim &#8211; warsztaty zdecydowanie nie byłyby tak udane bez pomocy mojej Ani. Prawdopodobnie nawet bym do nich nie dożył  
przygotowanie wszystkiego to dwa miesiące poszukiwań sali, zbierania materiałów i&#160;radykalnych zmian zdania co do sposobu przeprowadzenia zajęć,
takie warsztaty są świetnym pretekstem do dokładnego [...]]]></description>
			<content:encoded><![CDATA[<p>Ogólne podsumowanie umieściłem we&nbsp;<a href="http://warsztatyit.pl/2008/11/po-pierwszych-warsztatach/">wpisie na stronie Warsztatów IT</a>.  Tutaj dodam, że:</p>
<ul>
<li>przede wszystkim &ndash; warsztaty zdecydowanie nie byłyby tak udane bez pomocy mojej Ani. Prawdopodobnie nawet bym do nich nie dożył <img src='http://marcinkaszynski.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
<li>przygotowanie wszystkiego to dwa miesiące poszukiwań sali, zbierania materiałów i&nbsp;radykalnych zmian zdania co do sposobu przeprowadzenia zajęć,</li>
<li>takie warsztaty są świetnym pretekstem do dokładnego poznania prezentowanego materiału; dowiedziałem się paru nowych rzeczy, które będę stosował w&nbsp;moich aplikacjach,
</li>
<li>byłem zaskoczony, jak wiele firm wynajmujących sale notorycznie olewa klientów &ndash; rekordziści do dzisiaj nie przesłali informacji obiecanych przez telefon.  Kilkakrotnie.  We&nbsp;wrześniu.</li>
<li>zajęcia odbyły się w&nbsp;<a href="http://akademia.linuksa.pl/">Akademii Linuksa</a>; wszystkim chcącym wynająć salę komputerową mogę tę firmę tylko polecić &ndash; ludzie są pomocni i&nbsp;kompetentni, sprzęt sensowny.  Vista, Debian i&nbsp;Fedora, nie ma też problemu z&nbsp;dostępem do konta roota (w części firm warunkiem było korzystanie z&nbsp;vmware lub virtual pc).  Po całym dniu miałem tylko jedną uwagę: przydałoby się coś zrobić z&nbsp;okablowaniem (mieliśmy drobny incydent z&nbsp;nieszczęśliwie umieszczoną listwą zasilającą osiem komputerów).</li>
</ul>
<p>Ogólnie &ndash; niesamowicie pouczające doświadczenie; ciekawie było przekonać się, jak w&nbsp;praktyce wygląda organizacja takiej imprezy.</p>
<p>A już wkrótce kolejna edycja, jeśli znacie kogoś kto mógłby być zainteresowany &ndash; przekażcie, proszę, adres WarsztatyIT.pl <img src='http://marcinkaszynski.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2008/11/28/i-po-warsztatach/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Najlepsze serwisy w&#160;Django</title>
		<link>http://marcinkaszynski.com/blog/index.php/2008/11/06/najlepsze-serwisy-w-django/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2008/11/06/najlepsze-serwisy-w-django/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 14:18:33 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.elksoft.pl/index.php/2008/11/06/najlepsze-serwisy-w-django/</guid>
		<description><![CDATA[W ramach prac nad rozwojem długo oczekiwanego i&#160;niedawno otwartego polskiego serwisu Django odbywa się właśnie głosowanie na najlepsze polskie strony napisane z&#160;użyciem tej ramówki.  Po tygodniu dwa pierwsze miejsca zajmują Oiola i&#160;El Monito  
Lista jest interesująca: o&#160;Wydarzysie.net i&#160;wolnelektury.pl wiedziałem już wcześniej, ale o&#160;istnieniu sobotnianoc.pl, szarada.net, miejsce-na-reklame.pl, ocenfotke.pl czy rankingdeweloperow.pl dowiedziałem się dopiero teraz. [...]]]></description>
			<content:encoded><![CDATA[<p>W ramach prac nad rozwojem długo oczekiwanego i&nbsp;niedawno otwartego <a href="http://django.pl">polskiego serwisu Django</a> odbywa się właśnie <a href="http://djangopl.uservoice.com/pages/polskie_strony_w_django">głosowanie</a> na najlepsze polskie strony napisane z&nbsp;użyciem tej ramówki.  Po tygodniu dwa pierwsze miejsca zajmują <a href="http://oiola.com">Oiola</a> i&nbsp;<a href="http://el-monito.com">El Monito</a> <img src='http://marcinkaszynski.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Lista jest interesująca: o&nbsp;<a href="http://Wydarzysie.net">Wydarzysie.net</a> i&nbsp;<a href="http://www.wolnelektury.pl/">wolnelektury.pl</a> wiedziałem już wcześniej, ale o&nbsp;istnieniu <a href="http://www.sobotnianoc.pl/">sobotnianoc.pl</a>, <a href="http://szarada.net">szarada.net</a>, <a href="http://miejsce-na-reklame.pl/">miejsce-na-reklame.pl</a>, <a href="http://ocenfotke.pl/">ocenfotke.pl</a> czy <a href="http://rankingdeweloperow.pl/">rankingdeweloperow.pl</a> dowiedziałem się dopiero teraz.  Widać, że <a href="http://djangoproject.com">Django</a> jest używane coraz częściej, i&nbsp;to nie tylko przez hobbistów, ale też przez duże serwisy (<a href="http://grono.net">grono.net</a>, <a href="http://se.pl">Super Express</a> &ndash; ten ostatni przeniesiony z&nbsp;J2EE).</p>
<p>Jeśli jeszcze się zastanawiacie: to jest bardzo dobry moment żeby przyjrzeć się tej ramówce.  Jak to zwykle bywa z&nbsp;narzędziami oszczędzającymi olbrzymie ilości czasu, Django szybko zyskuje na popularności.  Teraz jeszcze zapewnia wyraźną przewagę konkurencyjną, ale niedługo stosowanie tego typu narzędzi będzie już koniecznością pozwalającą nadążyć.</p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2008/11/06/najlepsze-serwisy-w-django/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Warsztaty Django: zapisy otwarte</title>
		<link>http://marcinkaszynski.com/blog/index.php/2008/10/28/warsztaty-django-zapisy-otwarte/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2008/10/28/warsztaty-django-zapisy-otwarte/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 12:44:52 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.elksoft.pl/index.php/2008/10/28/warsztaty-django-zapisy-otwarte/</guid>
		<description><![CDATA[Od wczoraj można już zapisywać się na pierwszą edycję warsztatów "Tworzenie aplikacji w&#160;Django".  Liczba uczestników ograniczona do 12 osób, decyduje kolejność zgłoszeń.  Pierwsze cztery miejsca już zajęte, więc nie warto zwlekać &#8211; jeśli temat Cię interesuje, to zapisz się już teraz.
Szczegóły, jak zwykle, na stronie warsztatów.
]]></description>
			<content:encoded><![CDATA[<p>Od wczoraj można już zapisywać się na pierwszą edycję warsztatów "Tworzenie aplikacji w&nbsp;Django".  Liczba uczestników ograniczona do 12 osób, decyduje kolejność zgłoszeń.  Pierwsze cztery miejsca już zajęte, więc nie warto zwlekać &ndash; jeśli temat Cię interesuje, to <a href="http://warsztatyit.pl/django/rejestracja-200811/">zapisz się już teraz</a>.</p>
<p>Szczegóły, jak zwykle, <a href="http://warsztatyit.pl/django/">na stronie warsztatów</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2008/10/28/warsztaty-django-zapisy-otwarte/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Django: powiadomienia</title>
		<link>http://marcinkaszynski.com/blog/index.php/2008/10/25/django-powiadomienia/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2008/10/25/django-powiadomienia/#comments</comments>
		<pubDate>Sat, 25 Oct 2008 15:43:54 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Programowanie]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.elksoft.pl/index.php/2008/10/25/django-powiadomienia/</guid>
		<description><![CDATA[Wczoraj przyszło mi do głowy, że powiadomienia o&#160;błędach to jednocześnie jeden z&#160;bardziej przydatnych i&#160;najmniej widocznych elementów Django.  To dzięki nim zdarza mi się poprawić błędy i&#160;wysłać do użytkownika informację, że jakaś strona działa już poprawnie nawet jeśli nie chciało mu się zgłaszać usterki.
Na przykład:
&#160;
from django.shortcuts import render_to_response
&#160;
def gather_user_data&#40;user&#41;:
    # in reality [...]]]></description>
			<content:encoded><![CDATA[<p>Wczoraj przyszło mi do głowy, że powiadomienia o&nbsp;błędach to jednocześnie jeden z&nbsp;bardziej przydatnych i&nbsp;najmniej widocznych elementów Django.  To dzięki nim zdarza mi się poprawić błędy i&nbsp;wysłać do użytkownika informację, że jakaś strona działa już poprawnie <em>nawet jeśli nie chciało mu się zgłaszać usterki</em>.</p>
<p>Na przykład:</p>
<pre class="python">&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">shortcuts</span> <span style="color: #ff7700;font-weight:bold;">import</span> render_to_response
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> gather_user_data<span style="color: black;">&#40;</span><span style="color: #dc143c;">user</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># in reality this would be more complex</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'email'</span>: <span style="color: #dc143c;">user</span>.<span style="color: #dc143c;">email</span><span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> profile_view<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    data = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'user'</span>: request.<span style="color: #dc143c;">user</span><span style="color: black;">&#125;</span>
    data.<span style="color: black;">update</span><span style="color: black;">&#40;</span>gather_user_data<span style="color: black;">&#40;</span>request.<span style="color: #dc143c;">user</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'profile_view.html'</span>,
                              dictionary = data<span style="color: black;">&#41;</span>
&nbsp;</pre>
<p>Widok <code>profile_view</code> zawiera błąd ujawniający się tylko w&nbsp;niektórych sytuacjach.  Jeśli trafi na niego ktoś na serwerze produkcyjnym, zobaczy standardowe <i>500 Internal server error</i>, a&nbsp;Django automatycznie wyśle do mnie taki raport:</p>
<pre class="python">&nbsp;
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
&nbsp;
  File <span style="color: #483d8b;">&quot;/home/marcink/checkout/django-trunk/django/core/handlers/base.py&quot;</span>,
  line <span style="color: #ff4500;">86</span>, <span style="color: #ff7700;font-weight:bold;">in</span> get_response
    response = callback<span style="color: black;">&#40;</span>request, *callback_args, **callback_kwargs<span style="color: black;">&#41;</span>
&nbsp;
  File <span style="color: #483d8b;">&quot;/home/marcink/checkout/utils/blogowe/errtest/../errtest/errapp/views.py&quot;</span>,
  line <span style="color: #ff4500;">8</span>, <span style="color: #ff7700;font-weight:bold;">in</span> profile_view
    data.<span style="color: black;">update</span><span style="color: black;">&#40;</span>gather_user_data<span style="color: black;">&#40;</span>request.<span style="color: #dc143c;">user</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
  File <span style="color: #483d8b;">&quot;/home/marcink/checkout/utils/blogowe/errtest/../errtest/errapp/views.py&quot;</span>,
  line <span style="color: #ff4500;">4</span>, <span style="color: #ff7700;font-weight:bold;">in</span> gather_user_data
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'email'</span>: <span style="color: #dc143c;">user</span>.<span style="color: #dc143c;">email</span><span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #008000;">AttributeError</span>: <span style="color: #483d8b;">'AnonymousUser'</span> <span style="color: #008000;">object</span> has no attribute <span style="color: #483d8b;">'email'</span>
&nbsp;
&lt; wsgirequest GET:&lt; QueryDict: <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>&gt;,
POST:&lt; querydict : <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>&gt;,
COOKIES:<span style="color: black;">&#123;</span><span style="color: #483d8b;">'django_log_selectedLevel'</span>: <span style="color: #483d8b;">'0'</span>,
 <span style="color: #483d8b;">'django_log_showLocation'</span>: <span style="color: #483d8b;">'1'</span>,
 <span style="color: #483d8b;">'sessionid'</span>: <span style="color: #483d8b;">'915922a5710cf210e2f5fae47e0f8900'</span><span style="color: black;">&#125;</span>,
META:<span style="color: black;">&#123;</span><span style="color: #483d8b;">'COLORTERM'</span>: <span style="color: #483d8b;">'gnome-terminal'</span>,
 <span style="color: #483d8b;">'CONTENT_LENGTH'</span>: <span style="color: #483d8b;">''</span>,
 <span style="color: #483d8b;">'CONTENT_TYPE'</span>: <span style="color: #483d8b;">'text/plain'</span>,
 <span style="color: #483d8b;">'DBUS_SESSION_BUS_ADDRESS'</span>: <span style="color: #483d8b;">'unix:abstract=/tmp/dbus-BibuFgosrz,guid=c50cabac45d33af5b6936d0049024c87'</span>,
 <span style="color: #483d8b;">'DESKTOP_SESSION'</span>: <span style="color: #483d8b;">'default'</span>,
 <span style="color: #483d8b;">'DISPLAY'</span>: <span style="color: #483d8b;">':0.0'</span>,
 <span style="color: #483d8b;">'DJANGO_DIR'</span>: <span style="color: #483d8b;">'/home/marcink/checkout/django-trunk'</span>,
 <span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span>: <span style="color: #483d8b;">'errtest.settings'</span>,
 <span style="color: #483d8b;">'FCGI_PORT'</span>: <span style="color: #483d8b;">'9014'</span>,
 <span style="color: #483d8b;">'GATEWAY_INTERFACE'</span>: <span style="color: #483d8b;">'CGI/1.1'</span>,
 <span style="color: #483d8b;">'GDMSESSION'</span>: <span style="color: #483d8b;">'default'</span>,
 <span style="color: #483d8b;">'GDM_LANG'</span>: <span style="color: #483d8b;">'en_US.UTF-8'</span>,
 <span style="color: #483d8b;">'GDM_XSERVER_LOCATION'</span>: <span style="color: #483d8b;">'local'</span>,
 <span style="color: #483d8b;">'GNOME_DESKTOP_SESSION_ID'</span>: <span style="color: #483d8b;">'Default'</span>,
 <span style="color: #483d8b;">'GNOME_KEYRING_PID'</span>: <span style="color: #483d8b;">'7904'</span>,
 <span style="color: #483d8b;">'GNOME_KEYRING_SOCKET'</span>: <span style="color: #483d8b;">'/tmp/keyring-glnuCS/socket'</span>,
 <span style="color: #483d8b;">'GTK_RC_FILES'</span>: <span style="color: #483d8b;">'/etc/gtk/gtkrc:/home/marcink/.gtkrc-1.2-gnome2'</span>,
 <span style="color: #483d8b;">'HISTCONTROL'</span>: <span style="color: #483d8b;">'ignoreboth'</span>,
 <span style="color: #483d8b;">'HOME'</span>: <span style="color: #483d8b;">'/home/marcink'</span>,
 <span style="color: #483d8b;">'HTTP_ACCEPT'</span>: <span style="color: #483d8b;">'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'</span>,
 <span style="color: #483d8b;">'HTTP_ACCEPT_CHARSET'</span>: <span style="color: #483d8b;">'ISO-8859-1,utf-8;q=0.7,*;q=0.7'</span>,
 <span style="color: #483d8b;">'HTTP_ACCEPT_ENCODING'</span>: <span style="color: #483d8b;">'gzip,deflate'</span>,
 <span style="color: #483d8b;">'HTTP_ACCEPT_LANGUAGE'</span>: <span style="color: #483d8b;">'en-us,en;q=0.5'</span>,
 <span style="color: #483d8b;">'HTTP_CACHE_CONTROL'</span>: <span style="color: #483d8b;">'max-age=0'</span>,
 <span style="color: #483d8b;">'HTTP_CONNECTION'</span>: <span style="color: #483d8b;">'keep-alive'</span>,
 <span style="color: #483d8b;">'HTTP_COOKIE'</span>: <span style="color: #483d8b;">'sessionid=915922a5710cf210e2f5fae47e0f8900; django_log_showLocation=1; django_log_selectedLevel=0'</span>,
 <span style="color: #483d8b;">'HTTP_HOST'</span>: <span style="color: #483d8b;">'127.0.0.1:5003'</span>,
 <span style="color: #483d8b;">'HTTP_KEEP_ALIVE'</span>: <span style="color: #483d8b;">'300'</span>,
 <span style="color: #483d8b;">'HTTP_USER_AGENT'</span>: <span style="color: #483d8b;">'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.17) Gecko/20080922 Ubuntu/7.10 (gutsy) Firefox/2.0.0.17'</span>,
 <span style="color: #483d8b;">'JAVA_HOME'</span>: <span style="color: #483d8b;">'/home/marcink/devel/jre1.6.0/'</span>,
 <span style="color: #483d8b;">'LANG'</span>: <span style="color: #483d8b;">'en_US.UTF-8'</span>,
 <span style="color: #483d8b;">'LD_LIBRARY_PATH'</span>: <span style="color: #483d8b;">'/home/marcink/checkout/ldev_comicspot/comicspot/../other'</span>,
 <span style="color: #483d8b;">'LESSCLOSE'</span>: <span style="color: #483d8b;">'/usr/bin/lesspipe %s %s'</span>,
 <span style="color: #483d8b;">'LESSOPEN'</span>: <span style="color: #483d8b;">'| /usr/bin/lesspipe %s'</span>,
 <span style="color: #483d8b;">'LOGNAME'</span>: <span style="color: #483d8b;">'marcink'</span>,
 <span style="color: #483d8b;">'LS_COLORS'</span>: <span style="color: #483d8b;">'no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.flac=01;35:*.mp3=01;35:*.mpc=01;35:*.ogg=01;35:*.wav=01;35:'</span>,
 <span style="color: #483d8b;">'OLDPWD'</span>: <span style="color: #483d8b;">'/home/marcink'</span>,
 <span style="color: #483d8b;">'OTHER_DIR'</span>: <span style="color: #483d8b;">'/home/marcink/checkout/ldev_comicspot/comicspot/../other'</span>,
 <span style="color: #483d8b;">'OUTER_DIR'</span>: <span style="color: #483d8b;">'/home/marcink/checkout/ldev_comicspot/comicspot/..'</span>,
 <span style="color: #483d8b;">'PATH'</span>: <span style="color: #483d8b;">'/home/marcink/bin:/home/marcink/local/bin:/home/marcink/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games'</span>,
 <span style="color: #483d8b;">'PATH_INFO'</span>: u<span style="color: #483d8b;">'/profile/'</span>,
 <span style="color: #483d8b;">'PROJECT_BASE_DIR'</span>: <span style="color: #483d8b;">'/home/marcink/checkout/ldev_comicspot/comicspot'</span>,
 <span style="color: #483d8b;">'PROJECT_DIR'</span>: <span style="color: #483d8b;">'/home/marcink/checkout/ldev_comicspot/comicspot/comicspot'</span>,
 <span style="color: #483d8b;">'PROJECT_NAME'</span>: <span style="color: #483d8b;">'comicspot'</span>,
 <span style="color: #483d8b;">'PWD'</span>: <span style="color: #483d8b;">'/home/marcink/checkout/utils/blogowe/errtest'</span>,
 <span style="color: #483d8b;">'PYTHONPATH'</span>: <span style="color: #483d8b;">'/home/marcink/checkout/django-trunk'</span>,
 <span style="color: #483d8b;">'QUERY_STRING'</span>: <span style="color: #483d8b;">''</span>,
 <span style="color: #483d8b;">'REMOTE_ADDR'</span>: <span style="color: #483d8b;">'127.0.0.1'</span>,
 <span style="color: #483d8b;">'REMOTE_HOST'</span>: <span style="color: #483d8b;">''</span>,
 <span style="color: #483d8b;">'REQUEST_METHOD'</span>: <span style="color: #483d8b;">'GET'</span>,
 <span style="color: #483d8b;">'RUN_MAIN'</span>: <span style="color: #483d8b;">'true'</span>,
 <span style="color: #483d8b;">'SCRIPT_NAME'</span>: u<span style="color: #483d8b;">''</span>,
 <span style="color: #483d8b;">'SERVER_NAME'</span>: <span style="color: #483d8b;">'raven.loc'</span>,
 <span style="color: #483d8b;">'SERVER_PORT'</span>: <span style="color: #483d8b;">'5003'</span>,
 <span style="color: #483d8b;">'SERVER_PROTOCOL'</span>: <span style="color: #483d8b;">'HTTP/1.1'</span>,
 <span style="color: #483d8b;">'SERVER_SOFTWARE'</span>: <span style="color: #483d8b;">'WSGIServer/0.1 Python/2.5.1'</span>,
 <span style="color: #483d8b;">'SESSION_MANAGER'</span>: <span style="color: #483d8b;">'local/raven:/tmp/.ICE-unix/7907'</span>,
 <span style="color: #483d8b;">'SHELL'</span>: <span style="color: #483d8b;">'/bin/bash'</span>,
 <span style="color: #483d8b;">'SHLVL'</span>: <span style="color: #483d8b;">'1'</span>,
 <span style="color: #483d8b;">'SSH_AGENT_PID'</span>: <span style="color: #483d8b;">'7947'</span>,
 <span style="color: #483d8b;">'SSH_AUTH_SOCK'</span>: <span style="color: #483d8b;">'/tmp/ssh-lBRzQZ7907/agent.7907'</span>,
 <span style="color: #483d8b;">'TERM'</span>: <span style="color: #483d8b;">'xterm'</span>,
 <span style="color: #483d8b;">'TZ'</span>: <span style="color: #483d8b;">'America/Chicago'</span>,
 <span style="color: #483d8b;">'USER'</span>: <span style="color: #483d8b;">'marcink'</span>,
 <span style="color: #483d8b;">'USERNAME'</span>: <span style="color: #483d8b;">'marcink'</span>,
 <span style="color: #483d8b;">'WINDOWID'</span>: <span style="color: #483d8b;">'39852701'</span>,
 <span style="color: #483d8b;">'WINDOWPATH'</span>: <span style="color: #483d8b;">'7'</span>,
 <span style="color: #483d8b;">'XAUTHORITY'</span>: <span style="color: #483d8b;">'/tmp/.gdmELMXJU'</span>,
 <span style="color: #483d8b;">'XDG_DATA_DIRS'</span>: <span style="color: #483d8b;">'/usr/local/share/:/usr/share/:/usr/share/gdm/'</span>,
 <span style="color: #483d8b;">'XDG_SESSION_COOKIE'</span>: <span style="color: #483d8b;">'90de2c2a7bf31a95a76c4900471ce700-1224887428.976645-1927173936'</span>,
 <span style="color: #483d8b;">'_'</span>: <span style="color: #483d8b;">'/usr/bin/python'</span>,
 <span style="color: #483d8b;">'wsgi.errors'</span>: &lt; <span style="color: #008000;">open</span> <span style="color: #008000;">file</span> <span style="color: #483d8b;">'&lt; stderr&gt;'</span>, mode <span style="color: #483d8b;">'w'</span> at 0xb7dc30b0&gt;,
 <span style="color: #483d8b;">'wsgi.file_wrapper'</span>: &lt; <span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'django.core.servers.basehttp.FileWrapper'</span>&gt;,
 <span style="color: #483d8b;">'wsgi.input'</span>: &lt; <span style="color: #dc143c;">socket</span> ._fileobject <span style="color: #008000;">object</span> at 0x854a72c&gt;,
 <span style="color: #483d8b;">'wsgi.multiprocess'</span>: <span style="color: #008000;">False</span>,
 <span style="color: #483d8b;">'wsgi.multithread'</span>: <span style="color: #008000;">True</span>,
 <span style="color: #483d8b;">'wsgi.run_once'</span>: <span style="color: #008000;">False</span>,
 <span style="color: #483d8b;">'wsgi.url_scheme'</span>: <span style="color: #483d8b;">'http'</span>,
 <span style="color: #483d8b;">'wsgi.version'</span>: <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span>&gt;
&nbsp;</pre>
<p>Po pierwsze &ndash; dowiaduję się o&nbsp;problemie bez żadnej akcji ze&nbsp;strony użytkownika.  Po drugie &ndash; dostaję mnóstwo informacji o&nbsp;błędzie: opis wyjątku (tutaj &ndash; brak atrybutu email w&nbsp;AnonymousUser), dokładnie wskazane miejsce wystąpienia razem z&nbsp;pełnym stosem wywołań funkcji, zawartość parametrów przekazanych przez GET i&nbsp;POST i&nbsp;zawartość zmiennych środowiskowych.  W&nbsp;praktyce zwykle wystarcza to do złożenia testu pozwalającego na powtórzenie i&nbsp;usunięcie błędu.</p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2008/10/25/django-powiadomienia/feed/</wfw:commentRss>
		</item>
		<item>
		<title>&#8222;Django - 3 lata pracy i&#160;wszystko, co mamy, to marne 1.0&#8243;</title>
		<link>http://marcinkaszynski.com/blog/index.php/2008/10/13/django-3-lata-pracy-i-wszystko-co-mamy-to-marne-10/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2008/10/13/django-3-lata-pracy-i-wszystko-co-mamy-to-marne-10/#comments</comments>
		<pubDate>Mon, 13 Oct 2008 20:43:57 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Programowanie]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.elksoft.pl/index.php/2008/10/13/django-3-lata-pracy-i-wszystko-co-mamy-to-marne-10/</guid>
		<description><![CDATA[Z okazji wydania Django 1.0 na ostatnim Bootstrapie opowiedziałem o&#160;najważniejszych zmianach, jakie zaszły w&#160;tej ramówce podczas tych trzech lat, które upłynęły od momentu otwarcia kodu.  Slajdy z&#160;mojej prezentacji:

Reklama: już wkrótce odbędzie się pierwsza edycja warsztatów Django &#8211; najszybszy sposób na poznanie możliwości tego środowiska i&#160;rozpoczęcie pracy.
]]></description>
			<content:encoded><![CDATA[<p>Z okazji wydania Django 1.0 na ostatnim <a href="http://bootstrap.pl/2008/10/13/bootstrap-810-podsumowanie/">Bootstrapie</a> opowiedziałem o&nbsp;najważniejszych zmianach, jakie zaszły w&nbsp;tej ramówce podczas tych trzech lat, które upłynęły od momentu otwarcia kodu.  Slajdy z&nbsp;mojej prezentacji:</p>
<div style="width:425px;text-align:left" id="__ss_655203"><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=bootstrap200810-1223917787675541-9&stripped_title=django-3-lata-prac-i-wszystko-co-mamy-to-marne-10-presentation" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=bootstrap200810-1223917787675541-9&stripped_title=django-3-lata-prac-i-wszystko-co-mamy-to-marne-10-presentation" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
<p><b>Reklama</b>: już wkrótce odbędzie się pierwsza edycja <a href="http://warsztatyit.pl/django/">warsztatów Django</a> &ndash; najszybszy sposób na poznanie możliwości tego środowiska i&nbsp;rozpoczęcie pracy.</p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2008/10/13/django-3-lata-pracy-i-wszystko-co-mamy-to-marne-10/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Django na Bootstrapie</title>
		<link>http://marcinkaszynski.com/blog/index.php/2008/10/04/django-na-bootstrapie/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2008/10/04/django-na-bootstrapie/#comments</comments>
		<pubDate>Sat, 04 Oct 2008 13:56:22 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Programowanie]]></category>

		<category><![CDATA[Python]]></category>

		<category><![CDATA[web 2.0]]></category>

		<guid isPermaLink="false">http://blog.elksoft.pl/index.php/2008/10/04/django-na-bootstrapie/</guid>
		<description><![CDATA[Już w&#160;przyszłym tygodniu Bootstrap 8.10.  Andy Budd opowie o&#160;testach użyteczności (“Guerilla Usability Testing with Silverback”), a&#160;ja ponarzekam na Django ("Django - 3 lata prac i&#160;wszystko, co mamy, to marne 1.0").
Serdecznie zapraszamy.
]]></description>
			<content:encoded><![CDATA[<p>Już w&nbsp;przyszłym tygodniu <a href="http://bootstrap.pl/2008/10/03/810-czyli-wracamy-z-bootstrapem/">Bootstrap 8.10</a>.  <a href="http://www.clearleft.com/about/andy/">Andy Budd</a> opowie o&nbsp;testach użyteczności (“Guerilla Usability Testing with Silverback”), a&nbsp;ja ponarzekam na Django ("Django - 3 lata prac i&nbsp;wszystko, co mamy, to marne 1.0").</p>
<p>Serdecznie zapraszamy.</p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2008/10/04/django-na-bootstrapie/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Skróty: render_to_response</title>
		<link>http://marcinkaszynski.com/blog/index.php/2008/10/01/skroty-render_to_response/</link>
		<comments>http://marcinkaszynski.com/blog/index.php/2008/10/01/skroty-render_to_response/#comments</comments>
		<pubDate>Wed, 01 Oct 2008 14:27:24 +0000</pubDate>
		<dc:creator>Marcin Kaszyński</dc:creator>
		
		<category><![CDATA[Django]]></category>

		<category><![CDATA[Programowanie]]></category>

		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.elksoft.pl/index.php/2008/10/01/skroty-render_to_response/</guid>
		<description><![CDATA[Twórcy Django są bardzo skuteczni w&#160;eliminowaniu miejsc, które wymagałyby złamania zasady DRY.  Tym dziwniejszy jest wyjątek render_to_response: teoretycznie skrót, w&#160;praktyce &#8211; funkcja wymagająca codziennego wpisywania prawie identycznego kodu.
Wygląda to tak:
&#160;
from django.shortcuts import render_to_response
from django.template import RequestContext
def some_view&#40;request&#41;:
    return render_to_response&#40;'testapp/some_view.html',
             [...]]]></description>
			<content:encoded><![CDATA[<p>Twórcy Django są bardzo skuteczni w&nbsp;eliminowaniu miejsc, które wymagałyby złamania zasady <abbr title="Don't Repeat Yourself - Nie Powtarzaj Się">DRY</abbr>.  Tym dziwniejszy jest wyjątek <code>render_to_response</code>: teoretycznie skrót, w&nbsp;praktyce &ndash; funkcja wymagająca codziennego wpisywania prawie identycznego kodu.</p>
<p>Wygląda to tak:</p>
<pre class="python">&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">shortcuts</span> <span style="color: #ff7700;font-weight:bold;">import</span> render_to_response
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">template</span> <span style="color: #ff7700;font-weight:bold;">import</span> RequestContext
<span style="color: #ff7700;font-weight:bold;">def</span> some_view<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'testapp/some_view.html'</span>,
                              context_instance = RequestContext<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>,
                              dictionary = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'title'</span>: <span style="color: #483d8b;">'A very simple view'</span>,
                                            <span style="color: #483d8b;">'text'</span>: <span style="color: #483d8b;">'Some text here'</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;</pre>
<p>Parametr <code>context_instance</code> w&nbsp;praktyce zawsze wygląda tak samo.  Nazwa szablonu często, chociaż nie zawsze, przypomina nazwę funkcji obsługującej dany adres.  Parametr <code>dictionary</code> bywa na tyle rozbudowany, że najczęściej buduje się go wcześniej, żeby uniknąć bardzo długich lub sztucznie podzielonych linii.  Łączny poziom powtarzalności jest bardzo wyraźny po napisaniu kilku-kilkunastu widoków, zwłaszcza jeśli część z&nbsp;nich zawiera więcej niż jedną ścieżkę kończącą się wywołaniem <code>render_to_response</code>.</p>
<p>A przecież to może wyglądać tak:</p>
<pre class="python">&nbsp;
@with_template
<span style="color: #ff7700;font-weight:bold;">def</span> simple_view<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'title'</span>: <span style="color: #483d8b;">'A very simple view'</span>,
            <span style="color: #483d8b;">'text'</span>: <span style="color: #483d8b;">'Some text here'</span><span style="color: black;">&#125;</span>
&nbsp;</pre>
<p>W którymś momencie ta powtarzalność zirytowała mnie na tyle, że poświęciłem trochę czasu na napisanie odpowiedniego dekoratora.  Dla lenistwa.</p>
<p>Działa tak:</p>
<ul>
<li>jeśli funkcja zwraca <code>HttpResponse</code>, to dekorator nic nie zmienia &ndash; przekazuje ten wynik wyżej,</li>
<li>w przeciwnym wypadku zakłada, że wynikiem jest słownik (lub coś, co słownik udaje).  W&nbsp;takiej sytuacji przekazuje go do <code>render_to_response</code>, zakładając że wymagany szablon to "nazwa_aplikacji/nazwa_funkcji.html", a&nbsp;<code>context_instance</code> to standardowy <code>RequestContext</code>.
</li>
<li>dodatkowo, funkcja może zmienić nazwę szablonu: wystarczy, że w&nbsp;słowniku zwróci element 'template_name'.</li>
</ul>
<p>Przykłady:</p>
<pre class="python">&nbsp;
<span style="color: #808080; font-style: italic;"># plik testapp/views.py</span>
&nbsp;
@with_template
<span style="color: #ff7700;font-weight:bold;">def</span> simple_view<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'title'</span>: <span style="color: #483d8b;">'A very simple view'</span>,
            <span style="color: #483d8b;">'text'</span>: <span style="color: #483d8b;">'Some text here'</span><span style="color: black;">&#125;</span>
&nbsp;
@with_template
<span style="color: #ff7700;font-weight:bold;">def</span> simple_view_with_locals<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    title = <span style="color: #483d8b;">'Another simple view'</span>
    text = <span style="color: #483d8b;">'Some text here'</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">locals</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
@with_template
<span style="color: #ff7700;font-weight:bold;">def</span> complex_view<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> request.<span style="color: black;">REQUEST</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'redirect_me'</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> HttpResponseRedirect<span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://google.com/'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        template_name = <span style="color: #483d8b;">'testapp/some_other_template.html'</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">locals</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
@with_template<span style="color: black;">&#40;</span><span style="color: #483d8b;">'testapp/yet_another_template.html'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> view_with_template_override<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    title = <span style="color: #483d8b;">'Another simple view'</span>
    text = <span style="color: #483d8b;">'Some text here'</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">locals</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
@login_required
@with_template
<span style="color: #ff7700;font-weight:bold;">def</span> authenticated_view<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    text = <span style="color: #483d8b;">'Welcome, '</span> + request.<span style="color: #dc143c;">user</span>.<span style="color: black;">username</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">locals</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;</pre>
<p>Można też po prostu zwrócić <code>locals()</code> &ndash; słownik zawierający wszystkie zmienne lokalne.  Możliwe jest też, jak w&nbsp;ostatnim przykładzie, użycie innych dekoratorów, na przykład login_required.</p>
<p>Dekorator <code>with_template</code> ma też dodatkową, dużą zaletę: ułatwia wprowadzenie konwencji, zgodnie z&nbsp;którą nazwa szablonu wynika z&nbsp;nazwy aplikacji i&nbsp;funkcji.  Konwencje, ogólnie, to dobra rzecz.  Ta konkretna sprawia, że oszczędza się czas który normalnie poświęca się na decyzję jak nazwać szablon, wpisanie jego nazwy oraz późniejsze przeglądanie kodu żeby dowiedzieć się, jakiego szablonu należy się spodziewać pod danym adresem.</p>
<p>Owszem, można &ndash; jak zauważył ktoś podczas <a href="http://blog.elksoft.pl/index.php/2008/07/07/europython-2008/">europythonowej prezentacji</a> &ndash; dopisać informację o&nbsp;nazwie szablonu do dokumentacji funkcji, ale konwencje działają jak makra lub funkcje w&nbsp;dokumentacji: określa się je w&nbsp;jednym miejscu i&nbsp;stosuje w&nbsp;wielu, bez potrzeby zaglądania do tekstu.</p>
<pre class="python">&nbsp;
<span style="color: #808080; font-style: italic;"># plik testapp/urls.py</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span>.<span style="color: black;">urls</span>.<span style="color: black;">defaults</span> <span style="color: #ff7700;font-weight:bold;">import</span> *
&nbsp;
urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">'testapp.views'</span>,
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^normal/'</span>, <span style="color: #483d8b;">'normal_view'</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^simple/'</span>, <span style="color: #483d8b;">'simple_view'</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^complex/'</span>, <span style="color: #483d8b;">'complex_view'</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^authenticated/'</span>, <span style="color: #483d8b;">'authenticated_view'</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^view_with_template_override/'</span>, <span style="color: #483d8b;">'view_with_template_override'</span><span style="color: black;">&#41;</span>,
<span style="color: black;">&#41;</span>
&nbsp;</pre>
<p>I trochę testów:</p>
<pre class="python">&nbsp;
<span style="color: #808080; font-style: italic;"># plik testapp/tests.py</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> WithTemplateTestCase<span style="color: black;">&#40;</span>TestCase<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> test_views<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        response = <span style="color: #008000;">self</span>.<span style="color: black;">client</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/app/simple/'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTemplateUsed</span><span style="color: black;">&#40;</span>response, <span style="color: #483d8b;">'testapp/simple_view.html'</span><span style="color: black;">&#41;</span>
&nbsp;
        response = <span style="color: #008000;">self</span>.<span style="color: black;">client</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/app/complex/'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTemplateUsed</span><span style="color: black;">&#40;</span>response, <span style="color: #483d8b;">'testapp/some_other_template.html'</span><span style="color: black;">&#41;</span>
&nbsp;
        response = <span style="color: #008000;">self</span>.<span style="color: black;">client</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/app/complex/'</span>, data = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'redirect_me'</span>: <span style="color: #483d8b;">'1'</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>response.<span style="color: black;">status_code</span>, <span style="color: #ff4500;">302</span><span style="color: black;">&#41;</span>
&nbsp;
        response = <span style="color: #008000;">self</span>.<span style="color: black;">client</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/app/view_with_template_override/'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTemplateUsed</span><span style="color: black;">&#40;</span>response, <span style="color: #483d8b;">'testapp/yet_another_template.html'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">contrib</span>.<span style="color: black;">auth</span>.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> User
        <span style="color: #dc143c;">user</span>, created = User.<span style="color: black;">objects</span>.<span style="color: black;">get_or_create</span><span style="color: black;">&#40;</span>username = <span style="color: #483d8b;">'marcink'</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">user</span>.<span style="color: black;">set_password</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'marcink'</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">user</span>.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">client</span>.<span style="color: black;">login</span><span style="color: black;">&#40;</span>username=<span style="color: #483d8b;">'marcink'</span>, password = <span style="color: #483d8b;">'marcink'</span><span style="color: black;">&#41;</span>
        response = <span style="color: #008000;">self</span>.<span style="color: black;">client</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/app/authenticated/'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTemplateUsed</span><span style="color: black;">&#40;</span>response, <span style="color: #483d8b;">'testapp/authenticated_view.html'</span><span style="color: black;">&#41;</span>
&nbsp;</pre>
<p>A sam dekorator wygląda tak:</p>
<pre class="python">&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">http</span> <span style="color: #ff7700;font-weight:bold;">import</span> HttpResponse
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">shortcuts</span> <span style="color: #ff7700;font-weight:bold;">import</span> render_to_response
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">template</span> <span style="color: #ff7700;font-weight:bold;">import</span> RequestContext
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #808080; font-style: italic;"># functools appeared in Python 2.5</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> functools <span style="color: #ff7700;font-weight:bold;">import</span> wraps, update_wrapper
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #808080; font-style: italic;"># luckily for us, Django already backported it</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">utils</span>.<span style="color: black;">functional</span> <span style="color: #ff7700;font-weight:bold;">import</span> wraps, update_wrapper
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> with_template<span style="color: black;">&#40;</span>arg<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;
    A&nbsp;view decorator that handles rendering.
&nbsp;
    If the view returns a&nbsp;HttpResponse, it is passed intact; otherwise
    the returned value is passed as dictionary to render_to_response.
&nbsp;
    Usage samples:
&nbsp;
    @with_template
    def view_func(request, ...):
        return ...
&nbsp;
    @with_template('custom/template/name.html')
    def other_view_func(request, ...):
        return ...
    &quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">class</span> TheWrapper<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, default_template_name<span style="color: black;">&#41;</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">default_template_name</span> = default_template_name
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__call__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, func<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">def</span> decorated_func<span style="color: black;">&#40;</span>request, *args, **kwargs<span style="color: black;">&#41;</span>:
                ret = func<span style="color: black;">&#40;</span>request, *args, **kwargs<span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>ret, HttpResponse<span style="color: black;">&#41;</span>:
                    <span style="color: #ff7700;font-weight:bold;">return</span> ret
                <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span>ret.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'template_name'</span>,
                                                  <span style="color: #008000;">self</span>.<span style="color: black;">default_template_name</span><span style="color: black;">&#41;</span>,
                                          context_instance=RequestContext<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>,
                                          dictionary=ret<span style="color: black;">&#41;</span>
            update_wrapper<span style="color: black;">&#40;</span>decorated_func, func<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> decorated_func
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">callable</span><span style="color: black;">&#40;</span>arg<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> TheWrapper<span style="color: black;">&#40;</span>arg<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        app_name = <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'([^.]+)[.]views'</span>, arg.__module__<span style="color: black;">&#41;</span>.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
        default_template_name = <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>app_name, <span style="color: #483d8b;">'/'</span>, arg.__name__, <span style="color: #483d8b;">'.html'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> TheWrapper<span style="color: black;">&#40;</span>default_template_name<span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>arg<span style="color: black;">&#41;</span>
&nbsp;</pre>
<p>Pełen kod można znaleźć tutaj: <a href='http://blog.elksoft.pl/wp-content/uploads/2008/10/with_template_v2.zip'>testowy projekt with_template</a></p>
<p><em>Aktualizacja</em> 2008/10/13: zgodnie z&nbsp;sugestią urbana dodałem możliwość przekazania nazwy szablonu jako parametru dekoratora.</p>
]]></content:encoded>
			<wfw:commentRss>http://marcinkaszynski.com/blog/index.php/2008/10/01/skroty-render_to_response/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
