<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Jaros&#322;aw Zabie&#322;&#322;o - BLOG: Category Django</title>
    <link>http://blog.zabiello.com/articles/category/django</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>moje notatki, linki, komentarze</description>
    <item>
      <title>Skype3 i polski czat dla Rails&#243;w, Django i Pylonsa</title>
      <description>&lt;p&gt;Nowy Skype 3 wprowadza ma&#322;&#261; rewolucj&#281; w stos. do poprzedniej wersji. Mo&#380;na nie tylko rozmawia&#263;, ale pogra&#263; w szachy, k&#243;&#322;ko i krzy&#380;yk i inne gry (s&#261; b. &#322;adnie zrobione we Flashu 9). Mo&#380;na nagrywa&#263; rozmowy na dysk. Mo&#380;na tworzy&#263; publiczne czaty. I w&#322;a&#347;nie w tej sprawie pisz&#281; ten tekst bo 
stworzy&#322;em &lt;a href="http://www.skype.com/go/joinpublicchat?chat&amp;#38;skypename=hipertracker&amp;#38;topic=Rails%2C+Django%2C+Pylons+%28Polish%29&amp;#38;blob=qL-BIeEXX7A-qDj26JrmQcoze6L4kn_YE4016SUPrFY2DUmNoHxxVoeROiE4d1UZFQ4UJUo8-KPFDhFLqFhSVeo"&gt;polski czat dla mi&#322;o&#347;nik&#243;w framework&#243;w Ruby on Rails, Django i Pylons&lt;/a&gt;.
Wygodniej jest czasem skonsultowa&#263; co&#347; w czasie rzeczywistym ni&#380; na grupie czy &lt;a href="http://forum.rubyonrails.pl"&gt;forum dyskusyjnym&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Fri, 15 Dec 2006 00:48:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:6232652d-1ffd-4b4e-bcce-a630cc5bc711</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/12/15/skype3-i-polski-czat-dla-rails%C3%B3w-django-i-pylonsa</link>
      <category>Ruby on Rails</category>
      <category>Pylons</category>
      <category>Python</category>
      <category>Django (en)</category>
      <category>Ruby</category>
      <category>Django</category>
      <category>rails</category>
      <category>django</category>
      <category>pylons</category>
    </item>
    <item>
      <title>Nginx - Apache killer</title>
      <description>&lt;p&gt;W ostatnim artykule (&lt;a href="http://blog.zabiello.com/articles/2006/10/29/railsy-lighttpd-czy-apache-2-2-x"&gt;Railsy: Lighttpd czy Apache 2.2.x?&lt;/a&gt;) por&#243;wnywa&#322;em najbardziej popularne serwery &lt;span class="caps"&gt;HTTP&lt;/span&gt; dla &lt;a href="http://rubyonrails.org"&gt;Rails&#243;w&lt;/a&gt;. Zaintrygowany paroma &lt;a href="http://blog.zabiello.com/articles/2006/10/29/railsy-lighttpd-czy-apache-2-2-x#comments"&gt;wpisami w blogu&lt;/a&gt; postanowi&#322;em przyjrze&#263; si&#281; dosy&#263; ma&#322;o znanemu serwerowi &lt;span class="caps"&gt;HTTP&lt;/span&gt; kt&#243;ry zaczyna zdobywa&#263; coraz wi&#281;cej uwagi na Zachodzie. Chodzi o ultraszybki serwer &lt;a href="http://nginx.net"&gt;nginx&lt;/a&gt; napisany przez rosyjskiego programist&#281; Igora Sysojewa.&lt;/p&gt;


	&lt;p&gt;Na pierwszy b&#243;j poszed&#322; prosty test wy&#347;wietlenia &amp;#8220;Hello World!&amp;#8221; Na u&#380;ywanym przeze mnie serwerze dedykowanym (Athlon 64 3000+, 1GB &lt;span class="caps"&gt;RAM&lt;/span&gt;, Linux Ubuntu 64bit) dla 100 tys. zapyta&#324; (musia&#322;em u&#380;y&#263; a&#380; tyle, bo serwer jest za szybki na mniejsz&#261; liczb&#281; zapyta&#324;) uzyska&#322;em nast&#281;puj&#261;ce wyniki (dla polecenia &amp;#8220;ab -n 100000 -c 1 http://localhost&amp;#8221;):&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Apache 2.2.3 = 4439 req/s&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt; Lighttpd 1.4.11 = 7150 req/s&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt; Nginx 0.4.12 = 8700 req/s&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Co prawda Nginx wykazuje mia&#380;dz&#261;c&#261; przewag&#281; wydajno&#347;ci nad Apachem ale, z racji tego, &#380;e u&#380;ywam Lighttpd, kt&#243;ry co prawda odstaje od Nginxa ale nie a&#380; tak, postanowi&#322;em na razie zaczeka&#263; z ewentualn&#261; migracj&#261;.&lt;/p&gt;


	&lt;p&gt;Okaza&#322;o si&#281; jednak, &#380;e b&#281;d&#281; musia&#322; przeprowadzi&#263; tak&#261; migracj&#281; szybciej ni&#380; bym chcia&#322;. Co&#347; z&#322;ego zacz&#281;&#322;o si&#281; dzia&#263; z Ligthttpd. Po paru godzinach pracy, przestawa&#322; odpowiada&#263; na zapytania a nawet w og&#243;le proces znika&#322; z pami&#281;ci. Ki diabe&#322;? Trudno powiedzie&#263;, nie mam czasu aby analizowa&#263; dok&#322;adniej problem. Jedyne co pomaga&#322;o to regularny restart Lighttpd. Troch&#281; g&#322;upie rozwi&#261;zanie.  Postanowi&#322;em zatem zrobi&#263; wcze&#347;niejsz&#261; migracj&#281; do Nginxa. Wg &lt;a href="http://survey.netcraft.com/Reports/0609/byserver/nginx/index.html"&gt;statystyk Netcraftu&lt;/a&gt; z Nginxa korzysta ju&#380; ponad 90 tys. domen. Wydaje si&#281; to wystarczaj&#261;c&#261; ilo&#347;ci&#261; aby mo&#380;na by&#322;o uzna&#263; ten serwer za stabilny.&lt;/p&gt;


	&lt;p&gt;Jednak&#380;e moja migracja ma pewn&#261; trudno&#347;&#263;. U&#380;ywam bowiem r&#243;wnocze&#347;nie &lt;a href="http://php.net"&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt;&lt;/a&gt;, &lt;a href="djangoproject.com"&gt;Django&lt;/a&gt;, &lt;a href="http//rubyonrails.org"&gt;Rails&lt;/a&gt; i &lt;a href="http://zope.org"&gt;Zope&lt;/a&gt; (&#347;ci&#347;lej: &lt;a href="http://plone.org"&gt;Plone&lt;/a&gt;). Czyli ca&#322;kiem niez&#322;a mieszanka aplikacji. &lt;span class="caps"&gt;Z PHP&lt;/span&gt; i Railsami by&#322;o najmniej problem&#243;w, bo przyk&#322;ady konfiguracji s&#261; z grubsza podane w &lt;a href="http://wiki.codemongers.com/Nginx"&gt;Wiki&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Z Plone by&#322;o troszk&#281; gorzej. Musia&#322;em bowiem znale&#378;&#263; odpowiednik mniej wi&#281;cej takiego kodu w Apache:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;RewriteRule&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;^/(.*)$&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; 
&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;http://88.198.15.160:6001/VirtualHostBase/http/apologetyka.com:80/app/VirtualHostRoot/$1&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;  &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="constant"&gt;P&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="constant"&gt;L&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;To nie jest zwyk&#322;y rewrite, to jest po&#322;&#261;czenie proxy z rewrite.&lt;/p&gt;


	&lt;p&gt;W Lighttpd (te&#380; si&#281; swego czasu nam&#281;czy&#322;em aby to uzyska&#263;) uzyskuje si&#281; to tak:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;url&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;rewrite&lt;/span&gt;&lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;once&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;^/(.*)$&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/VirtualHostBase/http/apologetyka.com:80/plone/VirtualHostRoot/$1&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="ident"&gt;proxy&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;server&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;
   &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/VirtualHostBase/&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;
     &lt;span class="punct"&gt;(&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;host&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;88.198.15.160&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;6001&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

Troch&#281; pr&#243;b i si&#281; uda&#322;o. Nginx potrzebowa&#322; takiego wpisu:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;location&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
  &lt;span class="ident"&gt;rewrite&lt;/span&gt; ^&lt;span class="punct"&gt;/(.*)&lt;/span&gt;&lt;span class="global"&gt;$ &lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;VirtualHostBase&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;http&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;apologetyka&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;com&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="number"&gt;80&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;plone&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="constant"&gt;VirtualHostRoot&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="global"&gt;$1&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;location&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="constant"&gt;VirtualHostBase&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
  &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;opt&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;nginx&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;conf&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;proxy&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;conf&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
  &lt;span class="ident"&gt;proxy_pass&lt;/span&gt; &lt;span class="ident"&gt;http&lt;/span&gt;&lt;span class="punct"&gt;:/&lt;/span&gt;&lt;span class="regex"&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="number"&gt;88.198&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="number"&gt;15.160&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="number"&gt;6001&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Najtrudniej by&#322;o z konfiguracj&#261; &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt; bo opisu do Django na Nginx nie ma ani w  dokumentacji do Django, ani w dokumentacji do NGinxa. Zm&#281;czony eksperymentowaniem napisa&#322;em na list&#281; dyskusyjn&#261; Django i dosta&#322;em ca&#322;kiem po&#380;yteczn&#261; wskaz&#243;wk&#281; odno&#347;nie strony &lt;a href="http://www.python.rk.edu.pl/w/p/django-pod-serwerem-nginx/"&gt;http://www.python.rk.edu.pl/w/p/django-pod-serwerem-nginx/&lt;/a&gt;. Niestety mia&#322;em pecha, bo akurat trafi&#322;em na zmian&#281; wpis&#243;w w &lt;span class="caps"&gt;DNS&lt;/span&gt; i artyku&#322; by&#322; niedost&#281;pny. Uda&#322;o mi si&#281; na szcz&#281;&#347;cie wy&#322;uska&#263; jego kopi&#281; z cache Googli. Autor  mi&#281;dzyczasie podes&#322;a&#322; mi te&#380; pliki z artyku&#322;ami. Zauwa&#380;y&#322;em &#380;e napotka&#322; pewne problemy ze zmuszeniem Django do wy&#347;wietlania statycznej tre&#347;ci. Troch&#281; pod&#322;uba&#322;em w kodzie i problem rozwi&#261;za&#322;em. :)&lt;/p&gt;


	&lt;p&gt;Zauwa&#380;y&#322;em &#380;e Django wy&#347;wietla&#322; mi pliki statyczne w trybie debug. Wynika&#322;o to pewnie z tego, &#380;e w urls.py stosuj&#281; zawsze taki wpis:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;...&lt;/span&gt;
&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;DEBUG&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
  &lt;span class="ident"&gt;urlpatterns&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;patterns&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
    &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;^images/(?P&amp;lt;path&amp;gt;.*)$&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.views.static.serve&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;{'&lt;/span&gt;&lt;span class="string"&gt;document_root&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;MEDIA_ROOT&lt;/span&gt;&lt;span class="punct"&gt;+'&lt;/span&gt;&lt;span class="string"&gt;/images&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;show_indexes&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;}),&lt;/span&gt;
    &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;^stylesheets/(?P&amp;lt;path&amp;gt;.*)$&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.views.static.serve&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;{'&lt;/span&gt;&lt;span class="string"&gt;document_root&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;MEDIA_ROOT&lt;/span&gt;&lt;span class="punct"&gt;+'&lt;/span&gt;&lt;span class="string"&gt;/stylesheets&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;show_indexes&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;}),&lt;/span&gt;
    &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;^javascripts/(?P&amp;lt;path&amp;gt;.*)$&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.views.static.serve&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;{'&lt;/span&gt;&lt;span class="string"&gt;document_root&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;MEDIA_ROOT&lt;/span&gt;&lt;span class="punct"&gt;+'&lt;/span&gt;&lt;span class="string"&gt;/javascripts&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;show_indexes&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;}),&lt;/span&gt;
    &lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Dla trybu produkcyjnego (settings.DEBUG=False) trzeba zmusi&#263; serwer &lt;span class="caps"&gt;HTTP&lt;/span&gt; aby si&#281; zajmowa&#322; plikami statycznymi. Django ma tylko przetwarza&#263; Pythona. Mozna to zrobi&#263; np. tak:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;...&lt;/span&gt;
&lt;span class="ident"&gt;location&lt;/span&gt; ~&lt;span class="punct"&gt;*&lt;/span&gt; ^&lt;span class="punct"&gt;.+\.(&lt;/span&gt;&lt;span class="ident"&gt;jpg&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;jpeg&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;gif&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;png&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;ico&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;css&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;zip&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;tgz&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;gz&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;rar&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;bz2&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;doc&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;xls&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;exe&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;pdf&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;ppt&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;txt&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;tar&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;mid&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;midi&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;wav&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;bmp&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;rtf&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;js&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;mov&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
  &lt;span class="ident"&gt;access_log&lt;/span&gt;   &lt;span class="ident"&gt;off&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="comment"&gt;# po co mi logi obrazk&#243;w :)&lt;/span&gt;
  &lt;span class="ident"&gt;expires&lt;/span&gt;      &lt;span class="number"&gt;30&lt;/span&gt;&lt;span class="ident"&gt;d&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; 
&lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;location&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
  &lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;opt&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;nginx&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;conf&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;fastcgi&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;conf&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
  &lt;span class="ident"&gt;fastcgi_pass&lt;/span&gt; &lt;span class="number"&gt;127.0&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="number"&gt;0.1&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="number"&gt;6002&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
  &lt;span class="ident"&gt;fastcgi_pass_header&lt;/span&gt; &lt;span class="constant"&gt;Authorization&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
  &lt;span class="ident"&gt;fastcgi_intercept_errors&lt;/span&gt; &lt;span class="ident"&gt;off&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Gdzie plik fastcgi.conf:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;GATEWAY_INTERFACE&lt;/span&gt;  &lt;span class="constant"&gt;CGI&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="number"&gt;1.1&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;SERVER_SOFTWARE&lt;/span&gt;    &lt;span class="ident"&gt;nginx&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;QUERY_STRING&lt;/span&gt;       &lt;span class="global"&gt;$query_string&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;REQUEST_METHOD&lt;/span&gt;     &lt;span class="global"&gt;$request_method&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;CONTENT_TYPE&lt;/span&gt;       &lt;span class="global"&gt;$content_type&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;CONTENT_LENGTH&lt;/span&gt;     &lt;span class="global"&gt;$content_length&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;SCRIPT_NAME&lt;/span&gt;        &lt;span class="global"&gt;$fastcgi_script_name&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;REQUEST_URI&lt;/span&gt;        &lt;span class="global"&gt;$request_uri&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;DOCUMENT_URI&lt;/span&gt;       &lt;span class="global"&gt;$document_uri&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;DOCUMENT_ROOT&lt;/span&gt;      &lt;span class="global"&gt;$document_root&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;SERVER_PROTOCOL&lt;/span&gt;    &lt;span class="global"&gt;$server_protocol&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;REMOTE_ADDR&lt;/span&gt;        &lt;span class="global"&gt;$remote_addr&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;REMOTE_PORT&lt;/span&gt;        &lt;span class="global"&gt;$remote_port&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;SERVER_ADDR&lt;/span&gt;        &lt;span class="global"&gt;$server_addr&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;SERVER_PORT&lt;/span&gt;        &lt;span class="global"&gt;$server_port&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;SERVER_NAME&lt;/span&gt;        &lt;span class="global"&gt;$server_name&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;

&lt;span class="ident"&gt;fastcgi_param&lt;/span&gt;  &lt;span class="constant"&gt;PATH_INFO&lt;/span&gt;          &lt;span class="global"&gt;$fastcgi_script_name&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Plik startowy napisa&#322;em sobie ju&#380; w Pythonie:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;os&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;time&lt;/span&gt;
&lt;span class="constant"&gt;DEBUG&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;
&lt;span class="comment"&gt;# All Django project are inside /home/app/django/&lt;/span&gt;

&lt;span class="ident"&gt;path&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/home/app/django&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;projects&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;biblia&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
        &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;project&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;searchers&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
        &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;&lt;span class="number"&gt;6002&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
        &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;pidfile&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/var/run/django_searchers.pid&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
        &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;children&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="number"&gt;4&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
        &lt;span class="punct"&gt;},&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;koran&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt;
        &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;project&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django_project&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
        &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;&lt;span class="number"&gt;6003&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
        &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;pidfile&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/var/run/django_koran.pid&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
        &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;children&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="number"&gt;4&lt;/span&gt;
        &lt;span class="punct"&gt;},&lt;/span&gt;
    &lt;span class="punct"&gt;}&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="ident"&gt;project&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;projects&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;]['&lt;/span&gt;&lt;span class="string"&gt;project&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt;
    &lt;span class="ident"&gt;os&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;chdir&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;%s/%s/&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;path&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;project&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;
    &lt;span class="ident"&gt;appl&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;./manage.py runfcgi host=127.0.0.1&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="ident"&gt;cmd&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;%s port=%s minspare=1 maxspare=%s pidfile=%s --settings=%s.settings&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; \
          &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;appl&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;projects&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;]['&lt;/span&gt;&lt;span class="string"&gt;port&lt;/span&gt;&lt;span class="punct"&gt;'],&lt;/span&gt; &lt;span class="ident"&gt;projects&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;]['&lt;/span&gt;&lt;span class="string"&gt;children&lt;/span&gt;&lt;span class="punct"&gt;'],&lt;/span&gt; &lt;span class="ident"&gt;projects&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;]['&lt;/span&gt;&lt;span class="string"&gt;pidfile&lt;/span&gt;&lt;span class="punct"&gt;'],&lt;/span&gt; &lt;span class="ident"&gt;project&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;DEBUG&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="ident"&gt;cmd&lt;/span&gt;
    &lt;span class="ident"&gt;os&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;system&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;cmd&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="ident"&gt;pidfile&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;projects&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;]['&lt;/span&gt;&lt;span class="string"&gt;pidfile&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;os&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;path&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;exists&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;pidfile&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
        &lt;span class="ident"&gt;cmd&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/bin/kill -TERM %s&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="ident"&gt;open&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;pidfile&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;read&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;DEBUG&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="ident"&gt;cmd&lt;/span&gt;
        &lt;span class="ident"&gt;os&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;system&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;cmd&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;os&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;unlink&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;pidfile&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;restart&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="ident"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;time&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;sleep&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;__name__&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;__main__&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
    &lt;span class="ident"&gt;try&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
        &lt;span class="ident"&gt;action&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;project&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;argv&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;argv&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;','&lt;/span&gt;&lt;span class="string"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;restart&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; &lt;span class="keyword"&gt;and&lt;/span&gt; &lt;span class="ident"&gt;project&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="ident"&gt;projects&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
            &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
                &lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;project&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
            &lt;span class="ident"&gt;elif&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
                &lt;span class="ident"&gt;stop&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;project&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
            &lt;span class="ident"&gt;elif&lt;/span&gt; &lt;span class="ident"&gt;action&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;restart&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
                &lt;span class="ident"&gt;restart&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;project&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
            &lt;span class="keyword"&gt;else&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
                &lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="constant"&gt;IndexError&lt;/span&gt;
        &lt;span class="keyword"&gt;else&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
            &lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="constant"&gt;IndexError&lt;/span&gt;
    &lt;span class="ident"&gt;except&lt;/span&gt; &lt;span class="constant"&gt;IndexError&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
        &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Usage: %s {start|stop|restart} {%s}&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;%&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;argv&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;|&lt;/span&gt;&lt;span class="punct"&gt;'.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;projects&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;keys&lt;/span&gt;&lt;span class="punct"&gt;()))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Migracja si&#281; uda&#322;a. Plone, &lt;span class="caps"&gt;PHP&lt;/span&gt;, Django i Rails &#347;migaj&#261; mi teraz na ultraszybkim (i zajmuj&#261;cym ma&#322;o pami&#281;ci!) serwerze Nginx.  Acha, zapomnia&#322;em doda&#263;: Nginx to nie tylko du&#380;a wydajno&#347;&#263; i oszcz&#281;dno&#347;&#263; pami&#281;ci. Nginx ma du&#380;o  modu&#322;&#243;w. Mo&#380;e nie tyle, co Apache, ale znacznie lepiej ni&#380; Lighttpd.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;BTW&lt;/span&gt;, ciekawie wygl&#261;da tak&#380;e serwer &lt;a href="http://www.cherokee-project.com/"&gt;Cherokee&lt;/a&gt;. Nginx dzia&#322;a tylko pod systemami &lt;span class="caps"&gt;POSIX&lt;/span&gt; (Unix, MacOS-X, Linux, FreeBSD). Cherokee natomiast posiada&amp;#8230; binarn&#261; instalacj&#281; pod Windows!  Ale o tym mo&#380;e napisz&#281; co&#347; innym razem. :)&lt;/p&gt;</description>
      <pubDate>Wed, 08 Nov 2006 00:47:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:779dd78c-3248-4818-a9e4-1b2a20f8d7cb</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/11/08/nginx-apache-killer</link>
      <category>Ruby on Rails</category>
      <category>Django</category>
      <category>nginx</category>
      <category>django</category>
      <category>rails</category>
      <category>cherokee</category>
      <category>fastcgi</category>
    </item>
    <item>
      <title>Django Book</title>
      <description>&lt;p&gt;Zgodnie z wcze&#347;niejszymi zapowiedziami, autorzy &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt; postanowili nie tylko napisa&#263; ksi&#261;&#380;k&#281; na temat swego frameworka, ale tak&#380;e udost&#281;pnili za darmo ksi&#261;&#380;k&#281; w wersji online . Nowo powstaj&#261;ca ksi&#261;&#380;ka jest dost&#281;pna pod adresem &lt;a href="http://www.djangobook.com/"&gt;http://www.djangobook.com&lt;/a&gt;. Ka&#380;dy paragraf mo&#380;na komentowa&#263;. Wersja papierowa ma by&#263; wydana w 2007 przez wydawnictwo &lt;a href="http://apress.com/"&gt;Apress&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Wed, 01 Nov 2006 10:07:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:f2f246b5-1dc5-4563-9521-eca5bf461135</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/11/01/django-book</link>
      <category>Django</category>
      <category>django</category>
    </item>
    <item>
      <title>Django, Rails i wsp&#243;&#322;dzielenie danych</title>
      <description>&lt;p&gt;Osoby maj&#261;ce wcze&#347;niej do czynienia z innymi frameworkami, gdy si&#281;gn&#261; do &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt; mog&#261; by&#263; troch&#281; zdezorientowane sposobem w jaki nale&#380;y przekazywa&#263; zmienne do wsp&#243;lnych cz&#281;&#347;ci serwisu. Aby lepiej zrozumie&#263; problem, podam wpierw jak jest on rozwi&#261;zywane w &lt;a href="http://rubyonrails.com"&gt;Railsach&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Ot&#243;&#380;, Railsy zak&#322;adaj&#261;, &#380;e ka&#380;dy kontroler dziedziczy po wsp&#243;lnym kontrolerze zwanym &lt;strong&gt;ApplicationControler&lt;/strong&gt;. A &#380;e jest to normalna klasa Rubiego, wi&#281;c nic dziwnego, &#380;e wszelkie jej metody i zmienne (instancji) s&#261; automatycznie dziedziczone we wszystkich jej klasach potomnych. To bardzo intuicyjne rozwi&#261;zanie. Je&#347;li chcemy przekaza&#263; jakie&#347; wsp&#243;lne dane do wszystkich kontroler&#243;w i ich szablon&#243;w, wystarczy te dane zdefiniowa&#263; w tym miejscu. We&#378;my np. poni&#380;szy kod.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# plik: app/controllers/application.rb&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;ApplicationController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActionController&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Base&lt;/span&gt;
  &lt;span class="ident"&gt;before_filter&lt;/span&gt; &lt;span class="symbol"&gt;:defaults&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;
    &lt;span class="attribute"&gt;@name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Jarek&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;defaults&lt;/span&gt;
    &lt;span class="attribute"&gt;@msg&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Hello!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="comment"&gt;# plik: app/controllers/home_controller.rb&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;HomeController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt; 
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="comment"&gt;# plik: app/controllers/about_controller.rb&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;AboutController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt; 
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;index&lt;/span&gt;
    &lt;span class="attribute"&gt;@dodatkowa&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;warto&#347;&#263;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Zak&#322;adaj&#261;c, &#380;e nie zmieniali&#347;my domy&#347;lnego dzia&#322;ania resolvera adres&#243;w &lt;span class="caps"&gt;URL&lt;/span&gt;, wpisanie strony http://localhost:3000/home wywo&#322;a domy&#347;ln&#261; metod&#281; index() z klasy HomeController. Je&#347;li jej nie ma (jak na naszym przyk&#322;adzie), to Rails zak&#322;ada, &#380;e chcemy wywo&#322;a&#263; jej szablon tak, jakby ta metoda istnia&#322;a. Wczytywany jest zatem plik app/views/home/index.rhtml. Dzi&#281;ki temu, &#380;e w klasie ApplicationController zdefiniowali&#347;my 2 zmienne instancji (@name i @msg) automatycznie s&#261; one dziedziczone przez klas&#281; HomeController i tym samym dost&#281;pne w w/w szablonie. Identycznie b&#281;dzie z drug&#261; klas&#261;, jej szablon r&#243;wnie&#380; b&#281;dzie mia&#322; obie, zdefiniowane wy&#380;ej, zmienne&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;


	&lt;p&gt;W wypadku &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt;, sprawy wygl&#261;daj&#261; inaczej dlatego, &#380;e kontrolery&lt;sup&gt;&lt;a href="#fn3"&gt;3&lt;/a&gt;&lt;/sup&gt; nie s&#261; metodami klas Pythona! S&#261; one metodami &lt;strong&gt;modu&#322;u&lt;/strong&gt; Pythona. Co prawda modu&#322; te&#380; jest obiektem, ma w&#322;asn&#261; przetrze&#324; nazw itp. ale posiada jedn&#261; zasadnicz&#261; r&#243;&#380;nic&#281; wobec klasy &amp;#8211; &lt;strong&gt;nie mo&#380;na dziedziczy&#263;&lt;/strong&gt; modu&#322;u od modu&#322;u. Tym samym pr&#243;ba wsp&#243;&#322;dzielenia zmiennych musi by&#263; zrobiona zupe&#322;nie inn&#261; metod&#261;.&lt;/p&gt;


	&lt;p&gt;Troch&#281; z tym problemem si&#281; m&#281;czy&#322;em, bo w dokumentacji ma&#322;o na ten temat pisz&#261;. Dopiero na &lt;span class="caps"&gt;IRC&lt;/span&gt; podsuni&#281;to mi link do artyku&#322;u &lt;a href="http://www.b-list.org/weblog/2006/06/14/django-tips-template-context-processors"&gt;Django tips: Template context processors&lt;/a&gt;, kt&#243;ry wszystko &#322;adnie wyja&#347;ni&#322;&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;. Okazuje si&#281;, &#380;e jest kilka sposob&#243;w rozwi&#261;zania tego problemu. Napisanie w&#322;asnego MiddleWare (ech, nie chcia&#322;o mi si&#281;, to armata na much&#281;), napisanie w&#322;asnego znacznika dla szablon&#243;w (w wypadku mojej ma&#322;ej aplikacji, to te&#380; by&#322;aby przesada) lub wykorzystanie tzw. procesora kontekstu (Context Processor). I to by&#322;o to!&lt;/p&gt;


	&lt;p&gt;Wystarczy stworzy&#263; sobie plik (o nazwie np. context_processors.py) z funkcjami implementuj&#261;cymi to, co chcemy wrzuci&#263; do wszystkich szablon&#243;w.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
  &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Jarek&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;msg&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
  &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Hello!&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Nast&#281;pnie trzeba doda&#263; w settings.py informacj&#281; &#380;e b&#281;dziemy tego u&#380;ywa&#263;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;TEMPLATE_CONTEXT_PROCESSORS&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;
  &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;myapp.context_processors.name&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
  &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;myapp.context_processors.msg&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
  &lt;span class="punct"&gt;)&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;W wypadku &lt;a href="http://www.djangoproject.com/documentation/generic_views/"&gt;generic views&lt;/a&gt; to wszystko, bo one automatycznie wci&#261;gaj&#261; RequestContext dla swoich szablon&#243;w. W wypadku naszych kontroler&#243;w (zak&#322;adaj&#261;c, &#380;e u&#380;ywamy render_to_response() aby wy&#347;wietla&#263; szablon) trzeba na ko&#324;cu metody render_to_response() doda&#263; jeden parametr &amp;#8216;context_instance&amp;#8217;. Czyli:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# wpierw wci&#261;gamy RequestContext&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;template&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;RequestContext&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;home&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
  &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;render_to_response&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;home.html&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
    &lt;span class="ident"&gt;context_instance&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;RequestContext&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;about&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
  &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;render_to_response&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;about.html&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; 
    &lt;span class="punct"&gt;{'&lt;/span&gt;&lt;span class="string"&gt;dodatkowa&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;warto&#347;&#263;&lt;/span&gt;&lt;span class="punct"&gt;'},&lt;/span&gt;
    &lt;span class="ident"&gt;context_instance&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;RequestContext&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Tak coraz bardziej wg&#322;&#281;biaj&#261;c si&#281; w Rails i Django widz&#281;, &#380;e Rails jest jednak bardziej intuicyjny i &#322;atwiej si&#281; go nauczy&#263;. Jednak&#380;e Django wydaje si&#281; mie&#263; sporo pot&#281;&#380;nych mechanizm&#243;w, kt&#243;rych odkrywanie (mam nadziej&#281;) si&#281; upro&#347;ci jak tylko jego tw&#243;rcy opublikuj&#261; pierwsz&#261; ksi&#261;&#380;k&#281; na jego temat (ma by&#263; dost&#281;pna tak&#380;e w wersji online za darmo!)&lt;/p&gt;


	&lt;p&gt;&lt;del&gt;-&lt;/del&gt;&lt;/p&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; W podanym wy&#380;ej przyk&#322;adzie wykorzysta&#322;em dwa r&#243;&#380;ne sposoby przekazania zmiennych. Za pomoc&#261; konstruktora i za pomoc&#261; metody &amp;#8216;before_filter&amp;#8217;. Wiadomo, &#380;e konstruktor nie nadaje si&#281; do przekazywania wszystkiego. Czasami musimy przekaza&#263; co&#347;, co istnieje ju&#380; po wywo&#322;aniu konstruktora. Wtedy przydaje si&#281; metoda &amp;#8216;before_filter&amp;#8217;. To jedna z wielu sztuczek jakie ma w swym arsenale Rails aby kod by&#322; czysty, klarowny i zgodny z zasad&#261; &lt;span class="caps"&gt;DRY&lt;/span&gt; (nie powtarzania si&#281;).&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Zobacz te&#380; artyku&#322; &lt;a href="http://www.b-list.org/weblog/2006/06/13/how-django-processes-request"&gt;How Django processes a request?&lt;/a&gt;.&lt;/p&gt;


	&lt;p id="fn3"&gt;&lt;sup&gt;3&lt;/sup&gt; W Django nazywane s&#261; one metodami widoku. Osobi&#347;cie nie podoba mi si&#281; zamieszanie terminologiczne jakie Django zrobi&#322;o z modelem &lt;span class="caps"&gt;MVC&lt;/span&gt;. Kontroler to dla nich Widok (View), za&#347; Widok to Szablon. Troch&#281; to bez sensu, bo nikt tak tych rzecz nie nazywa. Czyli djangowe metody widoku to nic innego jak akcje kontrolera dla Rails i reszty &#347;wiata.&lt;/p&gt;</description>
      <pubDate>Wed, 19 Jul 2006 21:22:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:33840d51-676c-4426-a315-012a57809d60</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/07/19/django-rails-i-wsp%C3%B3%C5%82dzielenie-danych</link>
      <category>Ruby on Rails</category>
      <category>Django</category>
      <category>django</category>
      <category>rails</category>
    </item>
    <item>
      <title>Django i Rails bij&#261; PHP</title>
      <description>&lt;p&gt;&lt;a href="http://wiki.rubyonrails.com/rails/pages/Framework%20Performance"&gt;Por&#243;wnanie wydajno&#347;ci&lt;/a&gt; trzech framework&#243;w: &lt;a href="http://www.symfony-project.com/" title="PHP5"&gt;Symfony&lt;/a&gt;, &lt;a href="http://rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt; i &lt;a href="http://www.djangoproject.com/" title="Python"&gt;Django&lt;/a&gt; pokazuje &#380;e Rails jest znacznie szybszy od pehapowego Symfony, a Django znacznie szybszy od Rails&#243;w. Co ciekawe, &lt;span class="caps"&gt;PHP5&lt;/span&gt; u&#380;ywa&#322; akceleratora.&lt;/p&gt;</description>
      <pubDate>Fri, 14 Jul 2006 17:34:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:fdc523c1-2bf2-44ba-b27e-6bddd69d4adf</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/07/14/django-i-rails-bij%C4%85-php</link>
      <category>Ruby on Rails</category>
      <category>PHP</category>
      <category>Django</category>
      <category>django</category>
      <category>rails</category>
      <category>php</category>
    </item>
    <item>
      <title>Django i jego konkurenci</title>
      <description>&lt;p&gt;Po ostatnich paru &lt;a href="http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii"&gt;tekstach o Django&lt;/a&gt;, pora na odrobin&#281; odmiany, bo Django niekoniecznie musi by&#263; uwa&#380;any za najlepszy framework w klasie &#347;rodowisk &amp;#8220;railsopodobnych&amp;#8221;. :)&lt;/p&gt;


	&lt;h2&gt;TurboGears&lt;/h2&gt;


	&lt;p&gt;Trzeba pochwali&#263; dobry marketing megaframeworku&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;a href="http://www.turbogears.org/"&gt;TurboGears&lt;/a&gt;, bo ju&#380; w Amazonie jest nawet dost&#281;pna &lt;a href="http://www.amazon.com/gp/product/0132433885/102-4872618-4917751?adid=114F4FPZ5WP720AHCPNB&amp;#38;camp=14573&amp;#38;creative=327641&amp;#38;link%5Fcode=as1&amp;#38;n=283155"&gt;ksi&#261;&#380;ka&lt;/a&gt; na jego temat. Jednak&#380;e, ma&#322;e to pocieszenie. TurboGears raczej nie b&#281;dzie powa&#380;n&#261; alternatyw&#261; dla &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt; z prostej przyczyny. Ca&#322;y jego kr&#281;gos&#322;up opiera si&#281; na ma&#322;o profesjonalnej implementacji frameworka &lt;a href="http://cherrypy.org"&gt;CherryPy&lt;/a&gt;. Na ten temat by&#322;o sporo dyskusji na grupie pl.comp.lang.python, wi&#281;c nie b&#281;d&#281; si&#281; powtarza&#322;.&lt;/p&gt;


	&lt;h2&gt;Pylons&lt;/h2&gt;


	&lt;p&gt;&lt;a href="http://blog.zabiello.com/articles/2006/03/04/pylons-czyli-si%C5%82a-myghty-i-wygoda-rubyonrails"&gt;O Pylons pisa&#322;em wcze&#347;niej&lt;/a&gt;  ale nie w kontek&#347;cie &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt;. Moim zdaniem, Pylons jest jedynym frameworkiem, kt&#243;ry aktualnie mo&#380;e stanowi&#263; by&#263; realn&#261; alternatyw&#281; dla &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Wpierw trzeba napisa&#263; kilka s&#322;&#243;w wyja&#347;nienia dla tych, co my&#347;l&#261; &#380;e &lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt; to jaki&#347; taki zlepek innych bibliotek i framework&#243;w jak &lt;a href="http://www.turbogears.org/"&gt;TurboGears&lt;/a&gt;. Pylons to w&#322;a&#347;ciwie nic innego jak framework &lt;a href="http://myghty.org"&gt;Myghty&lt;/a&gt; tylko, &#380;e ze znacznie wi&#281;kszym prze&#322;o&#380;eniem akcent&#243;w na paradygmat &lt;span class="caps"&gt;MVC&lt;/span&gt; i podobie&#324;stwo do b&#281;dacych aktualnie &amp;#8220;na fali&amp;#8221; &lt;a href="http://rubyonrails.com"&gt;Rails&#243;w&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Tw&#243;rcy Myghty, mimo bardzo dobrej implementacji i wydajno&#347;ci nie mogli wcze&#347;niej przebi&#263; si&#281; do mi&#322;o&#347;nik&#243;w Pythona ze wzgl&#281;du na zbytnie podobie&#324;stwa do Perla (nic dziwnego, Myghty by&#322; wzorowany na bardzo dobrym perlowym &lt;a href="http://masonhq.com"&gt;Masonie&lt;/a&gt;, kt&#243;ry jest u&#380;ywany na dosy&#263; du&#380;&#261; skal&#281;)&lt;/p&gt;


	&lt;p&gt;Postanowiono wi&#281;c troszk&#281; dostosowa&#263; Myghty dla ludzi lubi&#261;cych prostot&#281; &lt;a href="http://python.org"&gt;Pythona&lt;/a&gt; i elegancj&#281; &lt;a href="http://rubyonrails.com"&gt;Ruby on Rails&lt;/a&gt;. I tak powsta&#322; &lt;strong&gt;Pylons&lt;/strong&gt;.&lt;/p&gt;


	&lt;h3&gt;Zalety Pylons&#243;w.&lt;/h3&gt;


	&lt;p&gt;&lt;a href="http://myghty.org"&gt;Myghty&lt;/a&gt; pozwala praktycznie na wymian&#281; wszystkich swoich &amp;#8220;podzespo&#322;&#243;w&amp;#8221;. W wypadku Pylons&#243;w, u&#380;yto resolvera adres&#243;w &lt;span class="caps"&gt;URL&lt;/span&gt; opartego na bibliotece &lt;a href="http://routes.groovie.org/"&gt;Routes&lt;/a&gt;. W skr&#243;cie mo&#380;na powiedzie&#263;, &#380;e &lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt; jest tu prawie identyczne jak Rails. &amp;#8220;Prawie&amp;#8221;, bo Routes jest &lt;strong&gt;pot&#281;&#380;niejszym&lt;/strong&gt; resolverem od tego co maj&#261; Railsy (pozwala np. na u&#380;ywanie wi&#281;kszych uog&#243;lnie&#324; i wyra&#380;e&#324; regularnych).&lt;/p&gt;


	&lt;h4&gt;Elastyczno&#347;&#263;&lt;/h4&gt;


	&lt;p&gt;Elastyczno&#347;&#263; Pylons&#243;w jest znacznie wi&#281;ksza od Django. W praktyce tam, gdzie stosuje si&#281; wstawki &lt;span class="caps"&gt;PHP&lt;/span&gt; do profesjonalnych system&#243;w &lt;span class="caps"&gt;CMS&lt;/span&gt; takich jak &lt;a href="http://reddot.pl"&gt;RedDot&lt;/a&gt;, Pylons dzi&#281;ki  swojej elastyczno&#347;ci i pot&#281;dze szablon&#243;w Myghty znacznie &#322;atwiej mo&#380;e wyprze&#263; tu &lt;span class="caps"&gt;PHP&lt;/span&gt;. Django jest systemem znacznie bardziej &lt;strong&gt;monolitycznym&lt;/strong&gt;. To jest jego zalet&#261; ale r&#243;wnocze&#347;nie tak&#380;e i &lt;strong&gt;wad&#261;&lt;/strong&gt; w wypadkach kiedy potrzebujemy znacznie wi&#281;kszej elastyczno&#347;ci.&lt;/p&gt;


	&lt;h4&gt;&lt;span class="caps"&gt;DRY&lt;/span&gt; w kontek&#347;cie generowania adres&#243;w &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/h4&gt;


	&lt;p&gt;Przewag&#261; korzystania z &lt;a href="http://routes.groovie.org/"&gt;Routes&lt;/a&gt; jest nie tylko prostota budowania adres&#243;w url bez konieczno&#347;ci posiadania wiedzy o wyra&#380;eniach regularnych. Najwi&#281;ksz&#261; zalet&#261; jest stosowanie helper&#243;w do budowania adres&#243;w &lt;span class="caps"&gt;URL&lt;/span&gt;. Identycznie jak w Railsach, jakakolwiek zmiana zasady rozwi&#261;zywania adres&#243;w, automatycznie przemapuje wszystkie adresy http we wszystkich szablonach. W wypadku Django musimy mozolnie poprawia&#263; wszystkie szablony. W wypadku du&#380;ego serwisu jest to kupa, niepotrzebnej roboty&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;


	&lt;h4&gt;Ajax i ca&#322;a reszta helper&#243;w z Ruby on Rails.&lt;/h4&gt;


	&lt;p&gt;Django (jak dot&#261;d) nie posiada wbudowanej implementacji Ajax&amp;#8217;a. Nie ma nawet jednomy&#347;lno&#347;ci jak&#261; bibliotek&#281; do tego celu mieliby u&#380;y&#263;&lt;sup&gt;&lt;a href="#fn3"&gt;3&lt;/a&gt;&lt;/sup&gt;. Poza tym Pylons implementuj&#261; wiele z &lt;a href="http://pylonshq.com/WebHelpers/module-index.html"&gt;helper&#243;w&lt;/a&gt; jakie maj&#261; Rails dost&#281;pne dla swoich szablon&#243;w.&lt;/p&gt;


	&lt;h4&gt;Pot&#281;ga szablon&#243;w Myghty&lt;/h4&gt;


	&lt;p&gt;Je&#347;li komu&#347; przeszkadzaj&#261; ma&#322;e mo&#380;liwo&#347;ci szablon&#243;w Django (celowo takie s&#261;, bo s&#261; kierowane do nieprogramist&#243;w) to mo&#380;liwo&#347;ci jakie daj&#261; szablony Myghty s&#261; po prostu powalaj&#261;ce. Je&#347;li kto&#347; m&#243;wi, &#380;e Django ma dobry cache, to niech si&#281; przyjrzy temu co potrafi&#261; wykorzystywane w Pylons &amp;#8211; szablony Myghty.&lt;/p&gt;


	&lt;p&gt;Ka&#380;dy szablon mo&#380;e by&#263; komponentem niezale&#380;nie keszowanym wg bardzo wyrafinowanych zasad (pot&#281;&#380;niejszych od tych, co oferuje Django) Regeneracja cache jest tak&#380;e inteligentnie napisana (podobnie jak to robi &lt;a href="http://skunkweb.sourceforge.net/"&gt;Skunkweb&lt;/a&gt;) Tzn. nigdy nie ma sytuacji, kiedy nadchodzi &#380;&#261;danie wy&#347;wietlenia strony i w tym samym momencie trzeba od&#347;wie&#380;y&#263; cache (bo si&#281; np. przeterminowa&#322;). Pylons w takim wypadku, odwleka operacj&#281; od&#347;wie&#380;ania cache&amp;#8217;a i podaje star&#261; zawarto&#347;&#263;. Regeneracja nast&#281;puje zaraz za tym requestem. W efekcie nigdy nie ma &#380;adnych &amp;#8220;czkawek&amp;#8221; w takiej krytycznej sytuacji.&lt;/p&gt;


	&lt;p&gt;Je&#347;li kto&#347; my&#347;li, &#380;e to bardzo rzadki przypadek, to niech sobie wyobrazi czy co si&#281; dzieje w wypadku naprawd&#281; du&#380;ego obci&#261;&#380;enia serwera. Pylons/Myghty by&#322; od pocz&#261;tku tworzony z my&#347;la pracy w sytuacji mocno obci&#261;&#380;onego serwera.&lt;/p&gt;


	&lt;p&gt;Szablony Myghty obs&#322;uguj&#261; nie tylko bardzo &lt;strong&gt;pot&#281;&#380;ne mechanizmy includowania&lt;/strong&gt; (tzn. mo&#380;na przekaza&#263; wiele r&#243;&#380;nych parametr&#243;w do includowanego szablonu w&#322;&#261;cznie z indywidualnymi zasadami keszowania). Myghty obs&#322;uguj&#261; tak&#380;e mechanizm dziedziczenia&lt;sup&gt;&lt;a href="#fn4"&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;


	&lt;h4&gt;Automatyczne generowanie dokumentacji.&lt;/h4&gt;


	&lt;p&gt;Pylonsy pozwalaj&#261; na &lt;a href="http://pylonshq.com/docs/0.8.2/adding_docs.html"&gt;automatyczne generowanie dokumentacji&lt;/a&gt; z projektu. Wykorzystuje do tego celu pythonowe &lt;a href="http://blog.zabiello.com/articles/2006/03/06/dokumentacja-dla-leniwych-pot%C4%99ga-pythona"&gt;docstringi&lt;/a&gt; i zamiast &lt;span class="caps"&gt;HTML&lt;/span&gt; &amp;#8211; reStructuredText (kt&#243;re s&#261; cz&#281;&#347;ci&#261; projektu &lt;a href="http://docutils.sf.net/"&gt;docutils&lt;/a&gt;)&lt;/p&gt;


	&lt;h4&gt;Zapakowanie projekt&#243;w do uniwersalnego formatu .egg.&lt;/h4&gt;


	&lt;p&gt;Pylonsy potrafi&#261; &lt;a href="http://pylonshq.com/docs/0.8.2/application_setup.html"&gt;zapakowa&#263; ca&#322;y projekt do paczki .egg&lt;/a&gt; co umo&#380;liwia bardzo &#322;atw&#261; dystrybucj&#281; aplikacji pylonsowych. Django tej (jak&#380;e po&#380;ytecznej) opcji w og&#243;le nie ma zaimplementowanej!&lt;/p&gt;


	&lt;h3&gt;Zalety Django.&lt;/h3&gt;


	&lt;p&gt;Mimo powy&#380;szych zalet Pylons&#243;w, Django ma tak&#380;e kilka swoich, dobrych stron.&lt;/p&gt;


	&lt;h4&gt;Lepsza dokumentacja.&lt;/h4&gt;


	&lt;p&gt;Dzi&#281;ki swojej monolityczno&#347;ci, Django dysponuje znacznie pe&#322;niejsz&#261; dokumentacj&#261; i jest ona zgromadzona w jednym miejscu. W wypadku Pylons&#243;w dokumentacja jest niezbyt wyczerpuj&#261;ca i porozrzucana. Wynika to w g&#322;&#243;wnej mierze z tego, &#380;e Pylons u&#380;ywa gotowych komponent&#243;w z innych projekt&#243;w.&lt;/p&gt;


	&lt;h4&gt;&#346;wietna obs&#322;uga formularzy.&lt;/h4&gt;


	&lt;p&gt;Django pracuje na wy&#380;szym poziomie abstrakcji odno&#347;nie pracy z formularzami. O ile nie potrzebujemy wi&#281;kszej elastyczno&#347;ci, to t&#261; kwesti&#281; maj&#261; doskonale zaprojektowan&#261;. Je&#347;li chcemy czego&#347; wi&#281;cej, mo&#380;emy przeci&#261;&#380;y&#263; metody jakie u&#380;ywa Django i wzbogaci&#263; je w dodatkowe opcje (np. obs&#322;ug&#281; zdarze&#324; javascript). Django obs&#322;uguje bardzo elegancko walidacj&#281; formularzy. Pylons TurboGears te&#380;) korzysta z &lt;a href="http://www.turbogears.org/about/extras.html#formencode"&gt;FormEncode&lt;/a&gt;, ale wydaje mi si&#281;, &#380;e Django jest tu jeszcze prostsze.&lt;/p&gt;


	&lt;h4&gt;&lt;span class="caps"&gt;ORM&lt;/span&gt;&lt;/h4&gt;


	&lt;p&gt;Djangowy korzysta z w&#322;asnego &lt;span class="caps"&gt;ORM&lt;/span&gt; (mapera relacyjno-obiektowego) Pylons korzysta z SQLObject. Oba &lt;span class="caps"&gt;ORM&lt;/span&gt;&amp;#8217;y s&#261; podobne, ale mnie si&#281; bardziej podoba ten, co ma Django. Moim zdaniem ma bardziej eleganck&#261; sk&#322;adni&#281;. Ma tak&#380;e lepsz&#261; dokumentacje. Troch&#281; to dziwne, bo SQLObject nie jest wcale nowym projektem. Mogliby si&#281; postara&#263; o   lepsz&#261; dokumentacj&#281;, bo ta co jest, jest fatalna.&lt;/p&gt;


	&lt;h4&gt;Panel admina.&lt;/h4&gt;


	&lt;p&gt;To jest wizyt&#243;wka Django. O ile nie potrzebujemy bardzo specyficznego jego dzia&#322;ania, to jest bardzo pomocny. To nie jest &#380;aden &amp;#8220;scaffolding&amp;#8221; z Rails&#243;w. To dopracowana aplikacja ko&#324;cowa.&lt;/p&gt;


	&lt;h4&gt;Generic views&lt;/h4&gt;


	&lt;p&gt;To kolejna wizyt&#243;wka Django. Za pomoc&#261; konfiguracji adres&#243;w (w pliku urls.py) i generic views mo&#380;na budowa&#263; ca&#322;e serwisy bez tworzenia ani jednego kontrolera. W ten spos&#243;b dzia&#322;a ca&#322;a &lt;a href="http://djangoproject.com"&gt;strona domowa&lt;/a&gt; Django. Osobi&#347;cie g&#322;&#281;boko nie wchodzi&#322;em w dzia&#322;anie tych mechanizm&#243;w, ale wygl&#261;daj&#261; bardzo interesuj&#261;co i mog&#261; da&#263;o gromne przy&#347;pieszenie w budowaniu stron www.&lt;/p&gt;


	&lt;h4&gt;Szersze wdro&#380;enia i silniejsze wsparcie komercyjne.&lt;/h4&gt;


	&lt;p&gt;Django mo&#380;e si&#281; poszczyci&#263; niez&#322;a list&#261; powa&#380;nych wdro&#380;e&#324;. Skala z&#322;ozono&#347;ci portal&#243;w zbudowanych w Django przewy&#380;sza to, czym si&#281; chwali strona domowa Rails&#243;w. Je&#347;li chodzi o Pylons, to wdro&#380;e&#324; jest bardzo ma&#322;o. Mo&#380;e brakuje im troch&#281; zmys&#322;u marketingowego jaki maj&#261; tw&#243;rcy Rails&#243;w i Turbogears? Na pewno brakuje lepszej, obszerniejszej dokumentacji wraz z wi&#281;ksz&#261; ilo&#347;ci&#261; przyk&#322;ad&#243;w.&lt;/p&gt;


	&lt;p&gt;Na bazie Django oferowany jest tak&#380;e odp&#322;atnie, komercyjny &lt;span class="caps"&gt;CMS&lt;/span&gt; (system zarz&#261;dania tre&#347;ci&#261;) &amp;#8211; &lt;a href="http://www.ellingtoncms.com/"&gt;Ellington&lt;/a&gt;. Specjalizowany jest do wi&#281;kszych serwis&#243;w, gazet itp. Firmy ceni&#261;ce sobie wsparcie komercyjne, nie musz&#261; si&#281; wi&#281;c obawia&#263;, &#380;e Django to jaki&#347; projekt paru zapale&#324;c&#243;w.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Django w rzeczy samej, jest projektem kt&#243;ry zosta&#322; wyekstraktowany z komercyjnego projektu &lt;a href="http://www.ellingtoncms.com/"&gt;Ellington&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;No i na koniec, &lt;em&gt;last but not least&lt;/em&gt;, tw&#243;rcom Django uda&#322;o si&#281; pozyska&#263; sympati&#281; samego tw&#243;rcy j&#281;zyka Pythona &amp;#8211; Guido van Rossum&amp;#8217;a. Na &lt;a href="http://python.org"&gt;stronie g&#322;&#243;wnej&lt;/a&gt;. Pythona w sekcji Web programming, obok Zope widzimy Django i Turbogears&amp;#8230;&lt;/p&gt;


	&lt;h3&gt;Podsumowanie.&lt;/h3&gt;


	&lt;p&gt;Django ma swoje zalety, ale nie jest wolny od wszelkich wad. Jednak&#380;e, og&#243;lnie rzecz bior&#261;c, to dobry framework, kt&#243;ry raczej nie powinien mie&#263; trudno&#347;ci w zdominowaniu dziedziby budowania aplikacji internetowych w Pythonie.&lt;/p&gt;


	&lt;p&gt;Jednak tam, gdzie liczy si&#281; wi&#281;ksza elastyczno&#347;&#263; i gdzie monolityczno&#347;&#263; Django jest nie do zaakceptowania, g&#322;&#243;wnym moim faworytem jest &lt;a href="http://pylonshq.com"&gt;Pylons&lt;/a&gt;. To jedyna realna alternatywa dla Django&lt;sup&gt;&lt;a href="#fn5"&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;del&gt;-&lt;/del&gt;&lt;/p&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Megaframework &amp;#8211; &#347;rodowisko zbudowane z gotowych, innych rozwi&#261;za&#324;. Turbogears korzysta m.in. z frameworku CherryPy, szablon&#243;w Kid, SQLObject jako &lt;span class="caps"&gt;ORM&lt;/span&gt; (mapera relacyjno obiektowego).&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Developerzy Django s&#261; przyciskani do muru &#380;&#261;daniami aby wprowadzi&#263; jaki&#347; mechanizm zast&#281;puj&#261;cy r&#281;czne wpisywanie adres&#243;w, i nie wykluczaj&#261;, &#380;e u&#380;yj&#261; Routes jako alternatywnego resolvera &lt;span class="caps"&gt;URL&lt;/span&gt;. Ale nie wiadomo kiedy i czy w og&#243;le to zrobi&#261;.&lt;/p&gt;


	&lt;p id="fn3"&gt;&lt;sup&gt;3&lt;/sup&gt;  Nie wiem dlaczego nie chca u&#380;y&#263; gotowych bibliotek jakie ju&#380; u&#380;ywa Pylons. Po co odkrywa&#263; na nowo ko&#322;o?&lt;/p&gt;


	&lt;p id="fn4"&gt;&lt;sup&gt;4&lt;/sup&gt; Dziedziczenie dzia&#322;a troch&#281; inaczej ni&#380; w Django i &lt;a href="http://cheetahtemplate.org"&gt;Cheetah&lt;/a&gt;. Np. nie ma tu, tak wygodnych &amp;#8220;blok&#243;w&amp;#8221; do przeci&#261;&#380;ania. Ale jest za to co&#347;, co przypomina &amp;#8220;akwizycj&#281;&amp;#8221; znan&#261; z &lt;a href="http://zope.org"&gt;Zope&lt;/a&gt;. Tzn. w Myghty mo&#380;na wrzuci&#263; do folderu z szablonami plik &amp;#8220;autohandler&amp;#8221; i automatycznie staje si&#281; szablonem bazowym dla wszystkich szablon&#243;w (bez dotykania ich zawarto&#347;ci!) To pozwala na wygodne zarz&#261;dzanie ca&#322;ymi grupami szablon&#243;w.&lt;/p&gt;


	&lt;p id="fn5"&gt;&lt;sup&gt;5&lt;/sup&gt; Poza oczywi&#347;cie Zope czy Plone, ale to jest troch&#281; inna bajka i temat na oddzielne rozwa&#380;ania. :)&lt;/p&gt;</description>
      <pubDate>Wed, 21 Jun 2006 17:18:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:d8ae9ac4-ed22-4de6-abae-f6338bec50f8</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/06/21/django-i-jego-konkurenci</link>
      <category>Pylons</category>
      <category>Django</category>
      <category>django</category>
      <category>pylons</category>
      <category>turbogears</category>
    </item>
    <item>
      <title>Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III.</title>
      <description>&lt;p&gt;W cz&#281;&#347;ci &lt;a href="http://blog.zabiello.com/articles/2006/05/27/django-wy%C5%BCszy-poziom-abstrakcji"&gt;pierwszej&lt;/a&gt;  i &lt;a href="http://blog.zabiello.com/articles/2006/05/27/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-ii"&gt;drugiej&lt;/a&gt;  opisa&#322;em podstawowe zalety Pythona i &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt;. Pora ma malutk&#261; demonstracj&#281; dzia&#322;aj&#261;cej aplikacji. B&#281;dzie to ma&#322;a, ale por&#281;czna wyszukiwarka biblijna (cho&#263; kod mo&#380;na &#322;atwo zaadoptowa&#263; do innych tre&#347;ci rzecz jasna). Jako baz&#281; u&#380;yj&#281; MySQL5. Zak&#322;adam tak&#380;e, &#380;e docelowo projekt b&#281;dzie chodzi&#322; pod Linuksem. Natomiast b&#281;dzie budowany i testowany pod Windowsami. Taki model pracy jest cz&#281;sto spotykany.  Django oczywi&#347;cie w wersji 0.95 &lt;span class="caps"&gt;SVN&lt;/span&gt;, czyli wersji pozbawionej wcze&#347;niejszej &amp;#8220;magii&amp;#8221; (kod Django jest teraz bardziej jawny i oparty na standardowych mechanizmach Pythona)&lt;/p&gt;


	&lt;h3&gt;Zaczynamy!&lt;/h3&gt;


	&lt;p&gt;Na pocz&#261;tku musimy stworzy&#263; projekt oraz aplikacj&#281; (Django w ramach jednego projektu potrafi obs&#322;ugiwa&#263; wiele aplikacji)&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;admin&lt;/span&gt;&lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;django&lt;/span&gt; &lt;span class="ident"&gt;startptoject&lt;/span&gt; &lt;span class="ident"&gt;myproject&lt;/span&gt;
&lt;span class="ident"&gt;cd&lt;/span&gt; &lt;span class="ident"&gt;myproject&lt;/span&gt;
&lt;span class="ident"&gt;manage&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;py&lt;/span&gt; &lt;span class="ident"&gt;startapp&lt;/span&gt; &lt;span class="ident"&gt;biblia&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Zauwa&#380;my, &#380;e skrypt admin-django uruchamiamy tylko raz. Potem ju&#380; pos&#322;ugujemy si&#281; skryptem manage.py. Dzi&#281;ki temu odpada nam kombinowanie z definiowaniem zmiennej systemowej &lt;span class="caps"&gt;DJANGO&lt;/span&gt;_SETTINGS_MODULE. List&#281; wszystkich dost&#281;pny opcji, zar&#243;wno dla django-admin.py jak i manage.py, uzyskamy uruchamiaj&#261;c te skrypty bez &#380;adnego parametru.&lt;/p&gt;


	&lt;h3&gt;Wst&#281;pna konfiguracja.&lt;/h3&gt;


Mamy zatem stworzony katalog z projektem i aplikacj&#261;. Wpierw trzeba skonfigurowa&#263; plik settings.py&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;. Na pocz&#261;tku pliku ustawiamy:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;

&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;platform&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;win32&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
    &lt;span class="constant"&gt;DEBUG&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;
&lt;span class="keyword"&gt;else&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="constant"&gt;DEBUG&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;False&lt;/span&gt;
&lt;span class="constant"&gt;TEMPLATE_DEBUG&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;DEBUG&lt;/span&gt;

&lt;span class="constant"&gt;ADMINS&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;Administrator&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;twoj@email&lt;/span&gt;&lt;span class="punct"&gt;'),&lt;/span&gt;
    &lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="constant"&gt;MANAGERS&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;ADMINS&lt;/span&gt;

&lt;span class="constant"&gt;DATABASE_ENGINE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;mysql&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="constant"&gt;DATABASE_NAME&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;myproject&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; 
&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;platform&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;win32&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
    &lt;span class="constant"&gt;DATABASE_USER&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;root&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="constant"&gt;DATABASE_PASSWORD&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="keyword"&gt;else&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="constant"&gt;DATABASE_USER&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;user_na_linuksie&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="constant"&gt;DATABASE_PASSWORD&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;haslo_pod_linuksem&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;platform&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;win32&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
    &lt;span class="constant"&gt;DATABASE_HOST&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="comment"&gt;# domyslnie bedzie localhost&lt;/span&gt;
&lt;span class="keyword"&gt;else&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="comment"&gt;# pod linuksem zwykle korzystamy z szybkiego gniazda unix&lt;/span&gt;
    &lt;span class="constant"&gt;DATABASE_HOST&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/var/run/mysqld/mysqld.sock&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="constant"&gt;DATABASE_PORT&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="comment"&gt;# czyli domy&#347;lnie b&#281;dzie 3306&lt;/span&gt;

&lt;span class="constant"&gt;ENABLE_PSYCO&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Kilka istotnych uwag.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Adres mailowy admina nie jest taki zupe&#322;nie nieistotny. W wypadku kiedy aplikacja na serwerze produkcyjnym si&#281; wy&#322;o&#380;y na jakim&#347; wyj&#261;tku, na ten adres jest automatycznie wysy&#322;any mail z wszystkimi szczeg&#243;&#322;ami. Trudno &#347;ledzi&#263;, czy w kt&#243;rym&#347; momencie aplikacja si&#281; nie wywali. Django zadba, aby &#380;aden taki wypadek nie umkn&#261;&#322; naszej uwadze&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Nale&#380;y sobie ustawi&#263; odpowiednie has&#322;a dost&#281;pu do MySQL5 pod windoz&#261; i pod linuksem.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Wa&#380;ne jest, aby wy&#322;&#261;czy&#263; obs&#322;ug&#281; akceleratora &lt;a href="http://psyco.sourceforge.net/"&gt;Psycho&lt;/a&gt;. To jeszcze nie jest dobrze przetestowane. Jak to mia&#322;em w&#322;&#261;czone, to pod Linuksem mia&#322;em problemy z dzia&#322;aniem djangowego panelu admina.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Musimy r&#281;cznie sobie stworzy&#263; (je&#347;li tego nie zrobili&#347;my) baz&#281;. Django za nas bazy nie stworzy. W naszym przypadku, tabelk&#281; na kt&#243;rej b&#281;dziemy pracowa&#263; mam ju&#380; gotow&#261; w bazie. Tu jest jej &lt;a href="http://zabiello.com/ftp/biblia_gdanska.zip"&gt;spakowany dump&lt;/a&gt; kt&#243;ry trzeba sobie za&#322;adowa&#263;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Pozosta&#322;e ustawienia:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;LANGUAGE_CODE&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;pl&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="comment"&gt;# domy&#347;lnie by&#322; angielski&lt;/span&gt;
&lt;span class="comment"&gt;#... &lt;/span&gt;
&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;platform&lt;/span&gt; &lt;span class="punct"&gt;==&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;win32&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt;
    &lt;span class="constant"&gt;MEDIA_ROOT&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;H:/home/myproject/biblia/public&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="keyword"&gt;else&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="constant"&gt;MEDIA_ROOT&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/home/myproject/biblia/public&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="comment"&gt;#... &lt;/span&gt;
&lt;span class="constant"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.contrib.sites&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
    &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;myproject.biblia&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Do s&#322;ownika &lt;span class="caps"&gt;INSTALLED&lt;/span&gt;_APPS musimy doda&#263; nasz&#261; aplikacj&#281; aby mo&#380;na by&#322;o jej u&#380;ywa&#263;. M&#243;wi o tym ostatnia linijka powy&#380;szego kodu. Zmienna &lt;span class="caps"&gt;MEDIA&lt;/span&gt;_ROOT musi by&#263; &lt;strong&gt;bezwzgl&#281;dn&#261; &#347;cie&#380;k&#261;&lt;/strong&gt; do plik&#243;w statycznych. Pod serwerem www odpowiada to zmiennej &lt;span class="caps"&gt;DOCUMENT&lt;/span&gt;_ROOT, czyli miejsca od kt&#243;rego serwer www cokolwiek widzi.&lt;/p&gt;


	&lt;h3&gt;Interaktywne testowanie Django z poziomu konsoli.&lt;/h3&gt;


W ka&#380;dej chwili mo&#380;emy odpali&#263; interaktywny dost&#281;p do &#347;rodowiska Django za pomoc&#261; komendy:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;manage&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;py&lt;/span&gt; &lt;span class="ident"&gt;shell&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
Warto sobie wcze&#347;niej zainstalowa&#263; &lt;a href="http://ipython.scipy.org/"&gt;ipythona&lt;/a&gt;, bo Django domy&#347;lnie pr&#243;buje uruchomi&#263; jego zamiast standardowy interpreter. Dzi&#281;ki ipythonowi mamy wspania&#322;e uzupe&#322;nianie metod do obiekt&#243;w + historia wczesniejszych operacji, kt&#243;ra nie znika wraz z zamkni&#281;ciem &lt;a href="http://ipython.scipy.org/"&gt;ipythona&lt;/a&gt;.

	&lt;h3&gt;Serwer.&lt;/h3&gt;


	&lt;p&gt;Mo&#380;emy odpali&#263; wbudowany serwer www za pomoc&#261; komendy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;manage&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;py&lt;/span&gt; &lt;span class="ident"&gt;runserver&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Domy&#347;lnie serwer si&#281; podniesie pod adresem http://127.0.0.1:8000. Mo&#380;na zmieni&#263; zar&#243;wno port jak i adres jak kto&#347; chce, rzecz jasna. Odpal manage.py (bez parametr&#243;w) to si&#281; dowiesz, jak.&lt;/p&gt;


	&lt;h3&gt;&lt;span class="caps"&gt;ORM&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;No dobrze, pora na co&#347; bardziej interesuj&#261;cego. Django operuje na relacyjnej bazie danych za pomoc&#261; swojego &lt;span class="caps"&gt;ORM&lt;/span&gt; (mapera relacyjno-obiektowego) Zalet takiego podej&#347;cia jest wiele. Wspomn&#281; tylko o tym, obiektowo mo&#380;na znacznie lepiej opisa&#263; dane modelu biznesowego ni&#380; to zrobi&#263; mo&#380;e czysty &lt;span class="caps"&gt;SQL&lt;/span&gt; ze swoimi kluczami obcymi i trigerami. Django wymaga aby w pliku myproject/biblia/models.py zdefiniowa&#263; dane dla &lt;span class="caps"&gt;ORM&lt;/span&gt;&amp;#8217;a. Zasada jest prosta: klasa odpowiada tabeli, a atrybuty klasy &amp;#8211; jej polom. Aby jednak sobie upro&#347;ci&#263; &#380;ycie, mo&#380;na pos&#322;u&#380;y&#263; si&#281; skryptem manage.py.&lt;/p&gt;


	&lt;p&gt;Poni&#380;szy skrypt robi &lt;strong&gt;introspekcj&#281; bazy&lt;/strong&gt; i wygeneruje pythonowe definicje wszystkich jej tabel. Jako parametr podajemy nazw&#281; naszej aplikacji (m&#243;wi&#322;em &#380;e Django jest zbudowane do pracy z wieloma aplikacjami w ramach projektu) Mo&#380;emy spokojnie zamaza&#263; plik models.py bo po stworzeniu projektu nic tam szczeg&#243;lnego nie ma.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;H&lt;/span&gt;&lt;span class="punct"&gt;:\&lt;/span&gt;&lt;span class="ident"&gt;home\myproject&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;&lt;span class="ident"&gt;manage&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;py&lt;/span&gt; &lt;span class="ident"&gt;inspectdb&lt;/span&gt; &lt;span class="ident"&gt;biblia&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;biblia&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;models&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;py&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Mamy zatem nasz&#261; wst&#281;pn&#261; obiektow&#261; definicj&#281; dla nasej tabelki:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;db&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;models&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;BibliaGdanska(models.Model):&lt;/span&gt;
    &lt;span class="ident"&gt;id&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;models&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;IntegerField&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;primary_key&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;ref&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;models&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;CharField&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;unique&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;maxlength&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;9&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;chapter_nr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;models&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;IntegerField&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;unique&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;verse_nr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;models&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;IntegerField&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;unique&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;verse&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;models&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;TextField&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Meta:&lt;/span&gt;
        &lt;span class="ident"&gt;db_table&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;biblia_gdanska&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Mo&#380;e sprawd&#378;my, czy to dzia&#322;a za pomoc&#261; interaktywnej konsoli:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_python "&gt;H:\home\myproject&amp;gt;manage.py shell
Deleting alias &amp;lt;dir&amp;gt;, it's a Python keyword or builtin.
Python 2.4.3 (#69, Apr 11 2006, 15:32:42) [MSC v.1310 32 bit (Intel)]
Type &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.

IPython 0.7.1.fix1 -- An enhanced Interactive Python.
?       -&amp;gt; Introduction to IPython's features.
%magic  -&amp;gt; Information about IPython's 'magic' % functions.
help    -&amp;gt; Python's own help system.
object? -&amp;gt; Details about 'object'. ?object also works, ?? prints more.

In [1]: from myproject.biblia.models import BibliaGdanska
In [2]: BibliaGdanska.objects.count()
Out[2]: 31151L&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Bingo! Wida&#263;, &#380;e dzia&#322;a.&lt;/p&gt;


	&lt;h3&gt;Kontroler i szablon.&lt;/h3&gt;


	&lt;p&gt;Teraz pora na nasz&#261; aplikacj&#281; internetow&#261;. Musimy stworzy&#263; kontroler. Z tajemniczych powod&#243;w developerzy Django zamiast &lt;span class="caps"&gt;MVC&lt;/span&gt; (model-view-controller) stosuj&#261; nazw&#281; &lt;span class="caps"&gt;MTV&lt;/span&gt; (model-template-view). W ka&#380;dym razie, to co zwykle nazywamy kontrolerem oni nazywaj&#261; widokiem (view) a to co nazywamy widokiem, oni nazywaj&#261; szablonem. Mniejsza o nazwy. Kontroler  tworzymy w pliku myproject/biblia/views.py&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#-*- coding: utf-8 -*-&lt;/span&gt;

&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;shortcuts&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;render_to_response&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;home&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;render_to_response&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;home.html&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Plik home.html jest szablonem. Stw&#243;rzmy na razie ten plik z napisem &amp;#8220;alama kota&amp;#8221; w &#347;rodku, aby zobaczy&#263;, czy to dzia&#322;a. Plik powinien le&#380;e&#263; w myproject/biblia/templates/home.html.&lt;/p&gt;


	&lt;h3&gt;Rozwi&#261;zywanie adres&#243;w &lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;Wpierw musimy powiedzie&#263; Django aby wiedzia&#322;, gdzie ma szuka&#263; naszego kontrolera. W tym celu dodajmy tak&#261; tre&#347;&#263; do pliku myproject/biblia/urls.py&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;conf&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;urls&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;defaults&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;settings&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;DEBUG&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;MEDIA_ROOT&lt;/span&gt;

&lt;span class="ident"&gt;urlpatterns&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;patterns&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
    &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;include&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;myproject.biblia.urls&lt;/span&gt;&lt;span class="punct"&gt;')),&lt;/span&gt;
    &lt;span class="comment"&gt;#(r'^admin/', include('django.contrib.admin.urls')),&lt;/span&gt;
&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="constant"&gt;DEBUG&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="ident"&gt;urlpatterns&lt;/span&gt; &lt;span class="punct"&gt;+=&lt;/span&gt; &lt;span class="ident"&gt;patterns&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;^images/(?P&amp;lt;path&amp;gt;.*)$&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.views.static.serve&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;{'&lt;/span&gt;&lt;span class="string"&gt;document_root&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;MEDIA_ROOT&lt;/span&gt;&lt;span class="punct"&gt;+'&lt;/span&gt;&lt;span class="string"&gt;/images&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;show_indexes&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;}),&lt;/span&gt;
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;^stylesheets/(?P&amp;lt;path&amp;gt;.*)$&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.views.static.serve&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;{'&lt;/span&gt;&lt;span class="string"&gt;document_root&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;MEDIA_ROOT&lt;/span&gt;&lt;span class="punct"&gt;+'&lt;/span&gt;&lt;span class="string"&gt;/stylesheets&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;show_indexes&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;}),&lt;/span&gt;
        &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;^javascripts/(?P&amp;lt;path&amp;gt;.*)$&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;django.views.static.serve&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;{'&lt;/span&gt;&lt;span class="string"&gt;document_root&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;MEDIA_ROOT&lt;/span&gt;&lt;span class="punct"&gt;+'&lt;/span&gt;&lt;span class="string"&gt;/javascripts&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;show_indexes&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;}),&lt;/span&gt;
    &lt;span class="punct"&gt;)&lt;/span&gt;    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Powy&#380;szy kod robi kilka rzeczy.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Wi&#261;&#380;e domy&#347;ln&#261; stron&#281; z naszym projektem. Wej&#347;cie na http://127.0.0.1:8000/ przeka&#380;e sterowanie do pliku myproject/biblia/urls.py (kt&#243;ry za chwilk&#281; stworzymy).&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Takie podej&#347;cie powoduje &#380;e ka&#380;da aplikacja mo&#380;e posiada&#263; swoje niezale&#380;ne zasady rozwi&#261;zywania adresu url. Dlatego oddelegowujemy obs&#322;ug&#281; &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;i do pliku urls.py wewn&#261;trz naszej aplikacji.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Zakomentowan&#261; linijk&#281; z panelem admina na razie zostawmy, wr&#243;c&#281; do tego p&#243;&#378;niej.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Ostatnie linijki s&#261; potrzebne do tego, aby Django obs&#322;ugiwa&#322; nie tylko plik Pythona ale tak&#380;e obrazki, style kaskadowe i skrypty j&#281;zyka JavaScript. Przyj&#261;&#322;em (wzoruj&#261;c si&#281; na &lt;a href="http://rubyonrails.com"&gt;Railsach&lt;/a&gt;) &#380;e s&#261; one odpowiednio w folderach myproject/biblia/public/images, myproject/biblia/public/stylesheets i myproject/biblia/public/javascripts.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;Dlaczego ten kod jest dost&#281;pny tylko dla &lt;span class="caps"&gt;DEBUG&lt;/span&gt;=True? Ano dlatego, &#380;e do pracy developerskiej pod windoz&#261; nie potrzebujemy &#380;adnego Apache&amp;#8217;a ani Lighttpd. Wystarczy wbudowany serwer www jaki dostarcza Django. Natomiast na serwerze produkcyjnym, gdzie chcemy uzyska&#263; najwi&#281;ksz&#261; wydajno&#347;&#263;, lepiej aby te pliki podawa&#322; serwer www i Django si&#281; tego nie dotyka&#322;o. Tak b&#281;dzie najlepiej i najszybciej.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Pozosta&#322; do skonfigurowania plik myproject/biblia/urls.py&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;conf&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;urls&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;defaults&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;*&lt;/span&gt;

&lt;span class="ident"&gt;urlpatterns&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;patterns&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;myproject.biblia.views&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
    &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;^$&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;home&lt;/span&gt;&lt;span class="punct"&gt;'),&lt;/span&gt;
   &lt;span class="comment"&gt;#(r'^admin/', include('django.contrib.admin.urls')),&lt;/span&gt;
&lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Tu r&#243;wnie&#380; mamy zakomentowany panel admina. Zostawmy go na razie w spokoju. Mo&#380;na uruchamia&#263;: http://127.0.0.1:8000/ powinno wy&#347;wietli&#263; nasz szablon z tre&#347;ci&#261; &amp;#8220;ala ma kota&amp;#8221;. No to mo&#380;e lepiej aby wy&#347;wietli&#263; co&#347; bardziej atrakcyjnego. Zbudujmy formularz.&lt;/p&gt;


	&lt;h3&gt;Formularz&lt;/h3&gt;


	&lt;p&gt;Formularze s&#261; zmor&#261; wi&#281;kszo&#347;ci programist&#243;w. S&#261; upierdliwe w ob&#322;udze, walidacji i co gorsze, ci&#261;gle z nimi mamy do czynienia. Aby u&#322;atwi&#263; nam &#380;ycie, Django stosuje specjaln&#261; technik&#281; tzw. &lt;a href="http://www.djangoproject.com/documentation/forms/"&gt;manipulator&#243;w&lt;/a&gt;,  aby praca z formularzami by&#322;a mi&#322;a i przyjemna. Musz&#281; przyzna&#263;, &#380;e to by&#322;a jedna z wa&#380;niejszych rzeczy, jaka mnie przyci&#261;gn&#281;&#322;a do Django. &lt;a href="htttp://pylonshq.com"&gt;Pylons&lt;/a&gt; i &lt;a href="http://rubyonrails.com"&gt;Rails&lt;/a&gt; maj&#261; swoje &lt;a href="http://pylonshq.com/WebHelpers/module-webhelpers.rails.html"&gt;helpery&lt;/a&gt;, ale nie s&#261; one a&#380; tak wygodne jak to, co oferuje Django&lt;sup&gt;&lt;a href="#fn3"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;


	&lt;p&gt;Zobaczmy jak si&#281; u&#380;ywa manipulatora. Wpierw zmie&#324;my nasz szablon (plik: myproject/biblia/templates/home.html). B&#281;dzie to prosty formularz z jednym polem gdzie wpiszemy wyszukiwane s&#322;owo.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_html "&gt;&amp;lt;form method=&amp;quot;get&amp;quot; action=&amp;quot;&amp;quot;&amp;gt;

    {% if form.q.errors %} 
        &amp;lt;div class=&amp;quot;formError&amp;quot;&amp;gt;
          Wpisz fraz&#281; o d&#322;ugo&#347;ci min. 3 znak&#243;w.
        &amp;lt;/div&amp;gt;
    {% endif %}

    {{ form.q }}
    &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;szukaj&amp;quot; /&amp;gt;

&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Manipulator.&lt;/h3&gt;


	&lt;p&gt;Teraz pora na manipulator. Musimy stworzy&#263; plik myproject/biblia/manipulators.py o przyk&#322;adowej tre&#347;ci:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;re&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;forms&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;core&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;validators&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;SzukajManipulator(forms.Manipulator):&lt;/span&gt;
    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;__init__&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
        &lt;span class="ident"&gt;regex&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;re&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;compile&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;(\w{3,})&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;re&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;U&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;fields&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;
            &lt;span class="ident"&gt;forms&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;TextField&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
                &lt;span class="ident"&gt;field_name&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;q&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
                &lt;span class="ident"&gt;length&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;30&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
                &lt;span class="ident"&gt;maxlength&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="number"&gt;255&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
                &lt;span class="ident"&gt;is_required&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;True&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
                &lt;span class="ident"&gt;validator_list&lt;/span&gt;&lt;span class="punct"&gt;=[&lt;/span&gt;&lt;span class="ident"&gt;validators&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;MatchesRegularExpression&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;regex&lt;/span&gt;&lt;span class="punct"&gt;)]&lt;/span&gt;
                &lt;span class="punct"&gt;),&lt;/span&gt;
            &lt;span class="punct"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Teraz zepnijmy wszystko razem w djangowym widoku (naszym kontrolerze). Zmie&#324;my tre&#347;&#263; pliku myproject/biblia/views.py na:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#-*- coding: utf-8 -*-&lt;/span&gt;

&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;shortcuts&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;render_to_response&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;forms&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;manipulators&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;SzukajManipulator&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;models&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="constant"&gt;BibliaGdanska&lt;/span&gt;

&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;home&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="ident"&gt;recordset&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;
    &lt;span class="ident"&gt;errors&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;_GET&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;{}&lt;/span&gt;
    &lt;span class="ident"&gt;manipulator&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;SzukajManipulator&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="comment"&gt;# tworz&#281; kopi&#281; parametr&#243;w przekazanych z formularza&lt;/span&gt;
    &lt;span class="ident"&gt;_GET&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;GET&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;copy&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;GET&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
        &lt;span class="comment"&gt;# sprawdzam czy formularz nie ma b&#322;&#281;d&#243;w&lt;/span&gt;
        &lt;span class="ident"&gt;errors&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;manipulator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;get_validation_errors&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;_GET&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="keyword"&gt;not&lt;/span&gt; &lt;span class="ident"&gt;errors&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
            &lt;span class="ident"&gt;manipulator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;do_html2python&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;_GET&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
           &lt;span class="comment"&gt;# wyszukuj&#281; cytaty &lt;/span&gt;
           &lt;span class="ident"&gt;recordset&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;BibliaGdanska&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;objects&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;all&lt;/span&gt;&lt;span class="punct"&gt;().&lt;/span&gt;&lt;span class="ident"&gt;filter&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;verse__icontains&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;_GET&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;q&lt;/span&gt;&lt;span class="punct"&gt;'])&lt;/span&gt;
    &lt;span class="ident"&gt;form&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;forms&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;FormWrapper&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;manipulator&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;_GET&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;errors&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;render_to_response&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;
        &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;home.html&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt;
        &lt;span class="punct"&gt;{'&lt;/span&gt;&lt;span class="string"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
         &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="ident"&gt;form&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
         &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;recordset&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="ident"&gt;recordset&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;
         &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;hits&lt;/span&gt;&lt;span class="punct"&gt;':&lt;/span&gt; &lt;span class="ident"&gt;len&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;recordset&lt;/span&gt;&lt;span class="punct"&gt;)})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Wy&#347;wietlenie wynik&#243;w.&lt;/h3&gt;


	&lt;p&gt;Aplikacja dzia&#322;a&lt;sup&gt;&lt;a href="#fn4"&gt;4&lt;/a&gt;&lt;/sup&gt;, ale nie wida&#263; wynik&#243;w. Wyniki wy&#347;wietlimy w  tym samym szablonie. Teraz b&#281;dzie wygl&#261;da&#322; tak:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_html "&gt;&amp;lt;form method=&amp;quot;get&amp;quot; action=&amp;quot;&amp;quot;&amp;gt;
    {% if form.q.errors %} 
        &amp;lt;div class=&amp;quot;formError&amp;quot;&amp;gt;
          Wpisz fraz&#281; o d&#322;ugo&#347;ci min. 3 znak&#243;w.
        &amp;lt;/div&amp;gt;
    {% endif %}    
    {{ form.q }}
    &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;szukaj&amp;quot; /&amp;gt;   
&amp;lt;/form&amp;gt;

{% if recordset %}
    &amp;lt;div&amp;gt;
      Znaleziono &amp;lt;b&amp;gt;{{ hits }}&amp;lt;/b&amp;gt; werset&#243;w:
    &amp;lt;/div&amp;gt;
    &amp;lt;ol&amp;gt;
    {% for row in recordset %}
        &amp;lt;li&amp;gt;
            {{ row.ref}} {{ row.chapter_nr}}:{{ row.verse_nr }} 
            &amp;amp;quot;{{ row.verse }}&amp;amp;quot;
        &amp;lt;/li&amp;gt;
    {% endfor %}
    &amp;lt;/ol&amp;gt;
{% else %}
    Nie znaleziono werset&#243;w dla frazy {{ request.GET.q }} :(
{% endif %}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Program powinien dzia&#322;a&#263;. Jednak w wypadku znalezienia mniej ni&#380; 5 werset&#243;w niezbyt po polsku zabrzmi wynik, np. &amp;#8220;Znaleziono 1 werset&#243;w&amp;#8221;. W wypadku j&#281;zyka angielskiego mo&#380;emy zmodyfikowa&#263; ten fragment szablonu za pomoc&#261; modyfikatora pluralize&lt;sup&gt;&lt;a href="#fn5"&gt;5&lt;/a&gt;&lt;/sup&gt;. Polski jezyk jest jednak znacznie bardziej wyrafinowany od angielskiego, bo u&#380;ywa 2 r&#243;&#380;nych form dla liczby mnogiej: 1 werset, 2 wersety, 5 werset&#243;w. Na szcz&#281;&#347;cie mo&#380;emy sobie zmieni&#263; spos&#243;b pracy tego modyfikatora.&lt;/p&gt;


	&lt;h3&gt;Przeci&#261;&#380;ene modyfikatora&lt;/h3&gt;


	&lt;p&gt;Aby nadpisa&#263; istniej&#261;cy modyfikator lub doda&#263; nowy, w&#322;asny, nale&#380;y stworzy&#263; wpierw folder myproject/biblia/templatetags z pustym plikiem o nazwie &lt;i&gt;init&lt;/i&gt;.py. Dodajemy tam drugi plik, o nazwie, powiedzmy: plugins.py o nast&#281;puj&#261;cej tre&#347;ci:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="ident"&gt;re&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;sys&lt;/span&gt;
&lt;span class="ident"&gt;from&lt;/span&gt; &lt;span class="ident"&gt;django&lt;/span&gt; &lt;span class="ident"&gt;import&lt;/span&gt;  &lt;span class="ident"&gt;template&lt;/span&gt;

&lt;span class="ident"&gt;register&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;template&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;Library&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;

&lt;span class="attribute"&gt;@register&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;filter&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;pluralize&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;pluralize&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Polish implementation&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;try&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
        &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;int&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;4&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
            &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;y&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
        &lt;span class="ident"&gt;elif&lt;/span&gt; &lt;span class="ident"&gt;int&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
            &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;\xc3\xb3w&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="comment"&gt;# utf8&lt;/span&gt;
    &lt;span class="ident"&gt;except&lt;/span&gt; &lt;span class="constant"&gt;ValueError&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="comment"&gt;# invalid string that's not a number&lt;/span&gt;
        &lt;span class="ident"&gt;pass&lt;/span&gt;
    &lt;span class="ident"&gt;except&lt;/span&gt; &lt;span class="constant"&gt;TypeError&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
        &lt;span class="ident"&gt;try&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
            &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;int&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;in&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;&lt;span class="number"&gt;4&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
                &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;y&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
            &lt;span class="ident"&gt;elif&lt;/span&gt; &lt;span class="ident"&gt;int&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="number"&gt;5&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
                &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;\xc3\xb3w&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="comment"&gt;# utf8            &lt;/span&gt;
        &lt;span class="ident"&gt;except&lt;/span&gt; &lt;span class="constant"&gt;TypeError&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 
            &lt;span class="ident"&gt;pass&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Zamiast polskiego znaczka &#243;, u&#380;y&#322;em zapisu &amp;#8217;\xc3\xb3&amp;#8217; bo to warto&#347;&#263; utf-8 i taki zapis jest niezale&#380;ny od tego, w czym otworzymy plik. Nikt przypadkowo nie popsuje nam polskich ogonk&#243;w.&lt;/p&gt;


	&lt;p&gt;Aby to zadzia&#322;a&#322;o, musimy gdzie&#347; na pocz&#261;tku &lt;strong&gt;w szablonie&lt;/strong&gt; doda&#263; linijk&#281;, kt&#243;ra za&#322;aduje nam now&#261; definicj&#281; modyfikatora pluralize.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;{%&lt;/span&gt; &lt;span class="ident"&gt;load&lt;/span&gt; &lt;span class="ident"&gt;plugins&lt;/span&gt; &lt;span class="punct"&gt;%}&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Kontekst i dziedziczenie szablon&#243;w.&lt;/h3&gt;


	&lt;p&gt;Nasz kod dzia&#322;a, ale kod &lt;span class="caps"&gt;HTML&lt;/span&gt; jest daleki od doskona&#322;o&#347;ci. Dobrze by&#322;oby dodac jaki&#347; nag&#322;&#243;wek, stopk&#281; itp. Django skopiowa&#322;o z pythonowych szablon&#243;w &lt;a href="http://cheetahtemplate.org/"&gt;Cheetah&lt;/a&gt; bardzo ciekawy spos&#243;b tworzenia kolejnych szablon&#243;w za pomoc&#261; obiektowego przeci&#261;&#380;ania starych.&lt;/p&gt;


	&lt;p&gt;Stw&#243;rzmy nasz szablon bazowy (myproject/biblia/templates/base.html)&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_html "&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Strict//EN&amp;quot; 
&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&amp;quot;&amp;gt;
&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; xml:lang=&amp;quot;en&amp;quot; lang=&amp;quot;en&amp;quot;&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;Przyk&#322;ad aplikacji w Django&amp;lt;/title&amp;gt;
        &amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot; /&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;    
         &amp;lt;h3&amp;gt;Wyszukiwarka Biblii Gda&#324;skiej&amp;lt;/h3&amp;gt;
         &amp;lt;h4&amp;gt; (przyk&#322;ad aplikacji w Django)&amp;lt;/h4&amp;gt;
          &amp;lt;div id=&amp;quot;main&amp;quot;&amp;gt;
          {% block main %}
              tutaj b&#281;dzie jaka&#347; nowa tre&#347;&#263;   
          {% endblock %}
          &amp;lt;/div&amp;gt;
        &amp;lt;hr size=&amp;quot;1&amp;quot; /&amp;gt;
        &amp;lt;div&amp;gt;
        &amp;amp;copy; 2006 
        &amp;lt;a href=&amp;quot;http://blog.zabiello.com&amp;quot;&amp;gt;Jaros&#322;aw Zabie&#322;&#322;o&amp;lt;/a&amp;gt;. 
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Ostatecznie szablon home.html b&#281;dzie wi&#281;c wygl&#261;da&#322; tak:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_html "&gt;{% extends &amp;quot;base.html&amp;quot; %}

{% load plugins %}

{% block main %}

&amp;lt;form method=&amp;quot;get&amp;quot; action=&amp;quot;&amp;quot;&amp;gt;
    {% if form.q.errors %} 
        &amp;lt;p class=&amp;quot;formError&amp;quot;&amp;gt;Wpisz fraz&#281; o d&#322;ugo&#347;ci min. 3  &amp;quot;znak&#243;w&amp;quot;.&amp;lt;/p&amp;gt;
    {% endif %}    
    {{ form.q }}
    &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;szukaj&amp;quot; /&amp;gt;   
&amp;lt;/form&amp;gt;

{% if recordset %}
    &amp;lt;div&amp;gt;Znaleziono &amp;lt;b&amp;gt;{{ hits }}&amp;lt;/b&amp;gt; werset{{ hits|pluralize }}:&amp;lt;/div&amp;gt;
    &amp;lt;ol&amp;gt;
    {% for row in recordset %}
        &amp;lt;li&amp;gt;
            {{ row.ref}} {{ row.chapter_nr}}:{{ row.verse_nr }} 
            &amp;amp;quot;{{ row.verse }}&amp;amp;quot;
        &amp;lt;/li&amp;gt;
    {% endfor %}
    &amp;lt;/ol&amp;gt;
{% else %}
    &amp;lt;p&amp;gt;Nie znaleziono werset&#243;w dla frazy &amp;lt;b&amp;gt;{{ request.GET.q }}&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;
{% endif %}

{% endblock %}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Szablon oparty na innym szablonie implementuje dowolne bloki z poprzedniego. Ca&#322;y pozosta&#322;y kontekst jest automatycznie dziedziczony. Takie podej&#347;cie bardzo skraca wielko&#347;&#263; szablon&#243;w i czyni je jeszcze bardziej czytelnymi.&lt;/p&gt;


	&lt;h3&gt;Pod&#347;wietlanie szukanej frazy.&lt;/h3&gt;


	&lt;p&gt;Do pliku plugins.py gdzie wcze&#347;niej zmienili&#347;my definicj&#281; modyfikatora pluralize, dodajmy kolejny. B&#281;dzie nam pod&#347;wietla&#322; w wersetach to, co szukamy.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="attribute"&gt;@register&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;filter&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;highlight&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;highlight&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;q&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="keyword"&gt;not&lt;/span&gt; &lt;span class="ident"&gt;isinstance&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;unicode&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt; 
        &lt;span class="ident"&gt;s&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;unicode&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;utf-8&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
    &lt;span class="ident"&gt;s&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;re&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt; &lt;span class="ident"&gt;compile&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;(&lt;/span&gt;&lt;span class="punct"&gt;'+&lt;/span&gt;&lt;span class="ident"&gt;re&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;escape&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;q&lt;/span&gt;&lt;span class="punct"&gt;)+'&lt;/span&gt;&lt;span class="string"&gt;)&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;re&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;U&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;re&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;I&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;sub&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;r&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&amp;lt;strong class=&amp;quot;highlight&amp;quot;&amp;gt;\1&amp;lt;/strong&amp;gt;&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="ident"&gt;s&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;encode&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;utf-8&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="ident"&gt;s&lt;/span&gt;    &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

W &#347;rodku zastosowano sztuczk&#281; z prze&#322;&#261;czeniem si&#281; na obiekty Unicode, aby mie&#263; pewno&#347;&#263; &#380;e polskie ogonki du&#380;e i ma&#322;e b&#281;d&#261; tak samo traktowane. W szablonie home.html wystarczy zmieni&#263; jedn&#261; linijk&#281;:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_html "&gt;{{ row.verse|highlight:request.GET.q }}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Co dalej?&lt;/h3&gt;


	&lt;p&gt;Mam nadziej&#281;, &#380;e artyku&#322; przybli&#380;y&#322; troch&#281; praktyczn&#261; stron&#281; uzywania Django. To dobry i szybki framework. Przyk&#322;adowe serwisy jakie w nim napisano s&#261; znacznie bardziej skomplikowane i wi&#281;ksze  ni&#380; te, co wida&#263; na stronie Rails. Django zosta&#322; napisany do szybkiego tworzenia ca&#322;kiem sporych serwis&#243;w&lt;/p&gt;


	&lt;p&gt;W kolejnym artykule, poka&#380;&#281; jak sobie wygodnie skonfigurowa&#263; panel admina kt&#243;ry udost&#281;pnia Django. Panel admina nie jest &#380;