<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.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: Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III.</title>
    <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>moje notatki, linki, komentarze</description>
    <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;adnym prostym rusztowaniem (scaffolding) do modyfikacji bazy. To kompletna aplikacja dla u&#380;ytkownika ko&#324;cowego. Bardzo wygodna i &#322;atwa w u&#380;yciu. Panel Django jest kolejn&#261; z jego cech, kt&#243;ra daje mu wyra&#378;n&#261; przewag&#281; w stosunku do konkurencji.&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; Kompletnie inaczej od 99% aplikacji pehapowych, gdzie o b&#322;&#281;dach dowiadujemy si&#281; najcz&#281;&#347;ciej dopiero wtedy, jak wszystko le&#380;y, albo jak kto&#347; &#322;askawie nas poinformuje.&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Jak wida&#263;, to normalny plik Pythona. &#379;adne chore &lt;span class="caps"&gt;XML&lt;/span&gt; i inne formaty nie s&#261; w og&#243;le nam potrzebne &amp;#8211; Python jest wystarczaj&#261;co dobry, aby &#322;atwo i przyjemnie prezentowa&#263; zagnie&#380;d&#380;one struktury. Inne j&#281;zyki, jak np. Java nie zbyt dobrze nadaj&#261; si&#281; do takich rzeczy, dlatego musz&#261; posi&#322;kowa&#263; si&#281; &lt;span class="caps"&gt;XML&lt;/span&gt;.&lt;/p&gt;


	&lt;p id="fn3"&gt;&lt;sup&gt;3&lt;/sup&gt; Tzn. Railsy si&#281; ju&#380; poprawi&#322;y, bo jest plugin kt&#243;ry dodaje im tak&#261; sam&#261; funkcjonalno&#347;&#263; jak Django. Nazywa si&#281; active-form i mo&#380;na go zainstalowa&#263; prosto spod &lt;a href="http://www.radrails.org/"&gt;RadRails&amp;#8217;a&lt;/a&gt;.&lt;/p&gt;


	&lt;p id="fn4"&gt;&lt;sup&gt;4&lt;/sup&gt; Kto nie wierzy, niech sobie wpisze print recordset po operacji wyszukiwania. Na konsoli serwera www wy&#347;wietli mu si&#281; zawarto&#347;&#263; tej zmiennej.&lt;/p&gt;


	&lt;p id="fn5"&gt;&lt;sup&gt;5&lt;/sup&gt; Szablony Django korzystaj&#261; ze sk&#322;adni modyfikator&#243;w podobnych do pehapowych &lt;a href="http://smarty.php.net/manual/en/language.modifiers.php"&gt;Smart&#243;w&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Mon, 12 Jun 2006 22:29:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:9ca089fe-040f-4a11-9c20-a33482827899</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii</link>
      <category>Python</category>
      <category>Django</category>
      <category>django</category>
    </item>
    <item>
      <title>"Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III." by Aras</title>
      <description>&lt;p&gt;Nie waln&#261;&#322;e&#347; sie przypadkiem z tymi przyk&#322;adowymi &amp;#8220;urls.py&amp;#8221; ?
Dwa razy ten sam plik z r&#243;&#380;n&#261; zawarto&#347;ci&#261; :/&lt;/p&gt;</description>
      <pubDate>Sat, 31 May 2008 13:18:15 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:179a926e-258c-4815-86db-07aa83f48306</guid>
      <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii#comment-1642</link>
    </item>
    <item>
      <title>"Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III." by conrad666</title>
      <description>&lt;p&gt;Rozszerzenie pluralize dodaje funkcjonalnosc dla templateow, a jak uzyskac cos podobnego dla panelu administratora? &amp;#8211; chodzi mi verbal_name, verbal_pluraral:&amp;gt;&lt;/p&gt;


	&lt;p&gt;pzdr&lt;/p&gt;</description>
      <pubDate>Thu, 10 Apr 2008 08:20:47 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:a084fb46-f960-4ca6-9836-ea7bcb069296</guid>
      <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii#comment-1556</link>
    </item>
    <item>
      <title>"Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III." by Swistak</title>
      <description>&lt;p&gt;Link do sql dump nie dzia&#322;a, czy m&#243;g&#322;bym poprosi&#263; o jego poprawienie?&lt;/p&gt;</description>
      <pubDate>Sun, 20 Jan 2008 04:21:10 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:cfd0ae10-40c9-40b2-8360-1b5c6f042390</guid>
      <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii#comment-1376</link>
    </item>
    <item>
      <title>"Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III." by valhallaman</title>
      <description>&lt;p&gt;hmmm &amp;#8230; mia&#322;o by&#263; milsze, szybsze i &#322;adniejsze ( no i bardziej czytelne ) ni&#380; railsy &amp;#8230;. cholerka, w RoR-ach scaffolding by to szybciutko za&#322;atwi&#322;, a tu cz&#322;owiek pisze i pisze &amp;#8230; nie wie dok&#322;adnie co &amp;#8230; urls.py jakie&#347; takie magiczne &amp;#8230; ;-) ...&lt;/p&gt;


	&lt;p&gt;sorki &amp;#8211; mia&#322;o by&#263; fajniej ni&#380; w railsach &amp;#8211;  nie widz&#281; tego :-( ...&lt;/p&gt;</description>
      <pubDate>Tue, 18 Jul 2006 09:45:45 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:3ca33cd1-d923-4e2e-ac67-d3a44fbf961f</guid>
      <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii#comment-161</link>
    </item>
    <item>
      <title>"Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III." by Adamh</title>
      <description>&lt;p&gt;dokumentaja generic views nie jest moze faktycznie bardzo intuicyjna ale gdy polaczymy ja z kodem django_website to naprawde szybko mozna wywnioskowac o co chodzi w sumie jest to dosc proste do odpalenia. 
W order_dict podajesz &amp;#8216;model&amp;#8217;: np Order (nie jako tekst a jako klase dolaczona wczesniej).&lt;/p&gt;


	&lt;p&gt;Powiedzmy, ze do sciezki /order/create/ dajesz akcje django.views.generic.create_update.create_object z drugim parametrem order_dict (ten oczywiscie moze miec wiecej parametrow ale model jest wymagany)
pozostaje tylko zbudowac szablon orders/order_form.html  w nim uzyc odwolanie do pola w modelu w ten sposob:
{{form.nazwa_pola}} (to jako czesc formularza) i juz:)&lt;/p&gt;</description>
      <pubDate>Wed, 14 Jun 2006 04:51:19 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:d2ef8ff5-0e6b-43d4-a26d-d4c54a5a43d2</guid>
      <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii#comment-145</link>
    </item>
    <item>
      <title>"Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III." by Podgladacz</title>
      <description>&lt;p&gt;Dzieki bardzo mi pom&#243;g&#322; ten artyku&#322;. Z niecierpliwo&#347;ci&#261; czekam na kolejny.&lt;/p&gt;</description>
      <pubDate>Tue, 13 Jun 2006 19:38:01 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:c66c4795-29d9-4ad8-9a81-55a64460c8bd</guid>
      <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii#comment-144</link>
    </item>
    <item>
      <title>"Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III." by Jaros&#322;aw Zabie&#322;&#322;o</title>
      <description>&lt;p&gt;Osobi&#347;cie, brakuje mi przyk&#322;ad&#243;w jak u&#380;ywa&#263; tych generic views. Z bie&#380;&#261;cej dokumentacji trudno si&#281; domy&#347;li&#263; jak zmontowa&#263; sobie np. taki CRUD.&lt;/p&gt;</description>
      <pubDate>Tue, 13 Jun 2006 19:27:51 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:aa6656f0-9d1f-4d5c-9ad2-f700a996f844</guid>
      <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii#comment-143</link>
    </item>
    <item>
      <title>"Django - zab&#243;jcza aplikacja. Cz&#281;&#347;&#263; III." by Adamh</title>
      <description>&lt;p&gt;Jesli chodzi o MVC/MVT to wlasnie nie jest to wcale tak &amp;#8220;dziwne&amp;#8221;.
Nie wiem czy przegladales kod django_website (darmowy projekt strony, na ktorej stoi djangoproject.com) i tam tworcy Django nie napisali ani jednego VIEW! Wszystko zrobili za pomoca Generic Views: &lt;a href="http://www.djangoproject.com/documentation/generic_views/" rel="nofollow"&gt;http://www.djangoproject.com/documentation/generic_views/&lt;/a&gt;
i szablonow.
Generic Views obluguja praktycznie wszystkie aspekty standardowych potrzeb przy wyswietlaniu danych  &amp;#8211; podajesz tylko odpowiedni QuerySet (w formacie ORM np Issues.objects.all()) i odpowiednie parametry.
Rozwiazanie jest genialne i dziala naprawde niezle. Dostarcza rowniez daleko posuniety CRUD gdzie to jak beda wygladaly formularze przygotowyjesz w szablonach a same pola masz dane &amp;#8220;automatycznie&amp;#8221;. 
Dziala to naprawde genialnie.&lt;/p&gt;</description>
      <pubDate>Tue, 13 Jun 2006 09:05:31 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:b55f47ec-0e57-4abe-bfab-ffacff3b6796</guid>
      <link>http://blog.zabiello.com/articles/2006/06/12/django-zab%C3%B3jcza-aplikacja-cz%C4%99%C5%9B%C4%87-iii#comment-141</link>
    </item>
  </channel>
</rss>
