| 27 | | * Powyższy szablon wyświetla przycisk typu ``"radio button"`` dla każdego wyboru ankiety. Pole ``value`` dla każdego radio button'a jest skojarzone z ID obiektu ``choice``. Atrybut ``name`` każdego radio button'a jest ``"choice"``. To oznacza, że jak ktoś wybiera jeden z radio button'ów i submit'uje formularz form, to wysłane zostaną dane za pomocą POST'a ``choice=3``. |
|---|
| 28 | | |
|---|
| 29 | | * Ustawiliśmy atrybut formularza ``action`` na ``/polls/{{ poll.id }}/vote/``, oraz ``method="post"``. Używanie ``method="post"`` (Przeciwne do ``method="get"``) jest bardzo ważne, ponieważ submit'owanie formularza zmieni dane po stronie serwera. Jeżeli kiedykolwiek tworzysz formularz który zmienia dane po stronie serwera, używaj ``method="post"``. Ta wskazówka nie ma nic wspólnego z Django, jest to dobra praktyka tworzenia aplikacji Web'owych. |
|---|
| 30 | | |
|---|
| 31 | | * ``forloop.counter`` oznacza ile razy tag ``for`` wykonał kod wewnątrz pętli. Więcej informacji znajdziesz w `dokumentacji dla tag'a "for"`_. |
|---|
| 32 | | |
|---|
| 33 | | .. _dokumentacji dla tag'a "for": http://www.djangoproject.com/documentation/templates/#for |
|---|
| 34 | | |
|---|
| 35 | | Teraz stwórzmy widok Django który obsługuje submit'owane dane oraz coś z nimi robi. |
|---|
| 36 | | Pamiętaj, że w `tutorial'u nr 3`, stworzyliśmy URLconf dla aplikacji pools, która zawiera linie:: |
|---|
| | 29 | * Powyższy szablon wyświetla przycisk typu ``"radio"`` dla każdego |
|---|
| | 30 | wyboru ankiety. Pole ``value`` dla każdego przycisku opcji jest skojarzone |
|---|
| | 31 | z ID obiektu ``choice``. Atrybut ``name`` każdego przycisku opcji jest |
|---|
| | 32 | dostępny w ``"choice"``. To oznacza, że jeśli ktoś wybiera jeden z |
|---|
| | 33 | przycisków i wysyła formularz form, to przeglądarka otrzyma metodą POST |
|---|
| | 34 | dane o zawartości ``choice=3``. |
|---|
| | 35 | |
|---|
| | 36 | * Ustawiliśmy atrybut formularza ``action`` na ``/polls/{{ poll.id }}/vote/`` |
|---|
| | 37 | oraz ``method`` na ``"post"``. Używanie ``method="post"`` (zamiast |
|---|
| | 38 | ``method="get"``) jest bardzo ważne, ponieważ wysyłanie formularza zmieni |
|---|
| | 39 | dane po stronie serwera. Jeżeli kiedykolwiek tworzysz formularz, który |
|---|
| | 40 | zmienia dane po stronie serwera, używaj ``method="post"``. Ta wskazówka |
|---|
| | 41 | nie ma nic wspólnego z Django, jest to dobra praktyka tworzenia aplikacji |
|---|
| | 42 | internetowych. |
|---|
| | 43 | |
|---|
| | 44 | * ``forloop.counter`` oznacza ile razy znacznik ``for`` wykonał kod wewnątrz pętli. |
|---|
| | 45 | Więcej informacji znajdziesz w `dokumentacji dla znacznika "for"`_. |
|---|
| | 46 | |
|---|
| | 47 | .. _dokumentacji dla znacznika "for": http://www.djangoproject.com/documentation/templates/#for |
|---|
| | 48 | |
|---|
| | 49 | Teraz utwórzmy widok Django, który obsługuje wysłane dane oraz coś z nimi robi. |
|---|
| | 50 | |
|---|
| | 51 | Pamiętaj, że w `tutorialu nr 3`_, utworzyliśmy URLconf dla aplikacji pools, |
|---|
| | 52 | która zawiera linie:: |
|---|
| 65 | | Ten kod zawiera kilka rzeczy o których jeszcze nie mowiliśmy w tym tutorial'u: |
|---|
| 66 | | |
|---|
| 67 | | * ``request.POST`` jest obiektem ala słownik, który pozwala na dostęp do submitowanych danych po nazwie klucza. |
|---|
| 68 | | W tym przypadku, ``request.POST['choice']`` |
|---|
| 69 | | zwraca ID wybranej opcji ankiety, jako string. Wartości z ``request.POST`` |
|---|
| 70 | | są zawsze string'ami. |
|---|
| 71 | | |
|---|
| 72 | | Django także dostarcza ``request.GET`` do pobierania danych z GET'a |
|---|
| 73 | | w ten sam sposób -- jednak używamy ``request.POST`` w naszym kodzie, |
|---|
| 74 | | aby upewnić się, że dane są tylko zmienione przez wywołanie POST. |
|---|
| 75 | | |
|---|
| 76 | | * ``request.POST['choice']`` rzuci wyjątek ``KeyError`` jeżeli ``choice`` |
|---|
| 77 | | nie byl dostarczony w danych z POST'a. |
|---|
| | 81 | Ten kod zawiera kilka rzeczy, o których jeszcze nie mówiliśmy w tym tutorialu: |
|---|
| | 82 | |
|---|
| | 83 | * ``request.POST`` jest obiektem przypominającym słownik, który pozwala |
|---|
| | 84 | na dostęp do otrzymanych danych po nazwie klucza. W tym przypadku |
|---|
| | 85 | ``request.POST['choice']`` zwraca (jako tekst) ID wybranej opcji ankiety. |
|---|
| | 86 | Wartości z ``request.POST`` są zawsze tekstami (obiektami string). |
|---|
| | 87 | |
|---|
| | 88 | Django także dostarcza również ``request.GET`` do pobierania w ten sam |
|---|
| | 89 | sposóbdanych z metody GET -- w naszym kodzie używamy jednak ``request.POST``, |
|---|
| | 90 | aby upewnić się, że dane będą zmieniane tylko przez wywołanie POST. |
|---|
| | 91 | |
|---|
| | 92 | * ``request.POST['choice']`` zgłosi wyjątek ``KeyError``, jeżeli ``choice`` |
|---|
| | 93 | nie byl dostarczony w danych metody POST. |
|---|
| 79 | | formularz ankiety z informacją o błędzie jeżeli ``choice`` nie był podany. |
|---|
| 80 | | |
|---|
| 81 | | * Po zwiększeniu liczny głosów(``selected_choice.votes += 1``), kod zwraca ``HttpResponseRedirect`` |
|---|
| 82 | | zamiast zwykłego ``HttpResponse``. |
|---|
| 83 | | ``HttpResponseRedirect`` przyjmuje pojedynczy argument: URL do którego |
|---|
| 84 | | użytkownik zostanie przekierowany(zobacz kolejny punkt jak tworzymy URL w tym przypadku). |
|---|
| 85 | | |
|---|
| 86 | | Zgodnie z komentarzem w kodzie, powinieneś zawsze zwracać ``HttpResponseRedirect`` |
|---|
| 87 | | po udanym obsłużeniu danych z POST'a. To nie jest specyficzne dla Django; |
|---|
| 88 | | to po prostu dobra praktyka przy tworzeniu aplikacji web'owych. |
|---|
| | 95 | formularz ankiety z informacją o błędzie, jeżeli ``choice`` nie był podany. |
|---|
| | 96 | |
|---|
| | 97 | * Po zwiększeniu liczny głosów (``selected_choice.votes += 1``), kod zwraca |
|---|
| | 98 | ``HttpResponseRedirect`` zamiast zwykłego ``HttpResponse``. |
|---|
| | 99 | ``HttpResponseRedirect`` przyjmuje pojedynczy argument: adres URL, do którego |
|---|
| | 100 | użytkownik zostanie przekierowany (zobacz kolejny punkt, jak tworzymy w |
|---|
| | 101 | tym przypadku adres URL). |
|---|
| | 102 | |
|---|
| | 103 | Zgodnie z komentarzem w kodzie, po udanym obsłużeniu danych z POST |
|---|
| | 104 | powinieneś zawsze zwracać obiekt ``HttpResponseRedirect``. |
|---|
| | 105 | To nie jest specyficzne dla Django; to po prostu dobra praktyka przy |
|---|
| | 106 | tworzeniu aplikacji internetowych. |
|---|
| 91 | | Ta funkcja pomaga uniknąć sztywnego wpisywania URL'a w funkcji widoku. |
|---|
| 92 | | Jako parametr przekazujemy nazwę widoku, który obsłuży nam zapytanie |
|---|
| 93 | | oraz zmienne które są użyte w tym URL'u, które wskazują na ten widok. |
|---|
| 94 | | W tym przypadku, używając URLConf który ustawiliśmy w tutorial'u 3, |
|---|
| 95 | | wywołanie ``reverse()`` zwróci string podobny do tego:: |
|---|
| | 109 | Ta funkcja pomaga uniknąć sztywnego wpisywania adresu URL w funkcji widoku. |
|---|
| | 110 | Jako parametr przekazujemy nazwę widoku, który obsłuży zapytanie |
|---|
| | 111 | oraz zmienne, które są użyte w tym adresie URL i wskazują na ten widok. |
|---|
| | 112 | W tym przypadku, używając URLConf, który ustawiliśmy w tutorialu 3, |
|---|
| | 113 | wywołanie ``reverse()`` zwróci tekst podobny do tego:: |
|---|
| 101 | | że musisz tutaj użyć pełnej nazwy widoku(łącznie z prefiksem). |
|---|
| 102 | | |
|---|
| 103 | | Więcej informacji o ``reverse()``, możesz znaleźć w `dokumentacji URL dispatcher'a`_. |
|---|
| 104 | | |
|---|
| 105 | | Jak wspomniano w tutorial'u 3, ``request`` jest obiektem ``HTTPRequest``. Więcej |
|---|
| 106 | | o obiektach ``HTTPRequest``, zobacz w `dokumentacji request and response`_. |
|---|
| 107 | | |
|---|
| 108 | | Po tym jak ktoś zagłosuje w ankiecie, widok ``vote()`` przekierowuje do strony z wynikami ankiety. |
|---|
| | 119 | że musisz tutaj użyć pełnej nazwy widoku (łącznie z prefiksem). |
|---|
| | 120 | |
|---|
| | 121 | Więcej informacji o ``reverse()`` możesz znaleźć w `dokumentacji URL dispatchera`_. |
|---|
| | 122 | |
|---|
| | 123 | Jak wspomniano w tutorialu 3, ``request`` jest obiektem ``HTTPRequest``. Więcej |
|---|
| | 124 | o obiektach ``HTTPRequest`` znajdziesz w `dokumentacji request and response`_. |
|---|
| | 125 | |
|---|
| | 126 | Po tym, jak ktoś zagłosuje w ankiecie, widok ``vote()`` przekierowuje do strony |
|---|
| | 127 | z wynikami ankiety. |
|---|
| | 128 | |
|---|
| 133 | | .. _dokumentacji URL dispatcher'a: http://www.djangoproject.com/documentation/url_dispatch#reverse |
|---|
| 134 | | |
|---|
| 135 | | Użyj widoków generycznych: Im mniej kodu tym lepiej |
|---|
| 136 | | =================================================== |
|---|
| 137 | | |
|---|
| 138 | | Widoki ``detail()`` (z `tutorial'a nr 3`_) oraz ``results()`` są po prostu głupio |
|---|
| 139 | | proste -- i jak wspomniano wczesniej, nadmiarowe. Widok ``index()`` (także z |
|---|
| 140 | | tutorial'a nr 3), który wyświetla listę ankiet, jest podobny. |
|---|
| 141 | | |
|---|
| 142 | | Te widoki wykonują często powtarzane czynności w aplikacji www: pobranie danych |
|---|
| 143 | | z bazy danych zgodnie z parametrem przekazanym w URL'u, załadowaniem szablonu |
|---|
| 144 | | oraz zwróceniem przetworzonego szablonu. Ponieważ jest to tak często wykonywane, |
|---|
| 145 | | Django dostarcza skrót, zwany systemem "widoków generycznych". |
|---|
| 146 | | |
|---|
| 147 | | Widoki generyczne są abstrakcją do punktu w którym nie musisz nawet pisać |
|---|
| 148 | | kodu w Pythonie aby napisać aplikacje. |
|---|
| 149 | | |
|---|
| 150 | | Przeróbmy teraz naszą aplikacje ankiet aby używała systemu widoków generycznych, |
|---|
| 151 | | możemy więc skasować trochę kodu który napisaliśmy wcześniej. Musimy tylko wykonać |
|---|
| 152 | | kilka kroków aby dokonać tej konwersji. |
|---|
| 153 | | |
|---|
| 154 | | .. admonition:: Dlaczego zmieniamy w ten sposób kod ? |
|---|
| 155 | | |
|---|
| 156 | | Generalnie, gdy piszesz aplikacje w Django, musisz ocenić czy widoki generyczne |
|---|
| 157 | | są dobrym rozwiązaniem Twojego problemu, jeżeli tak, to będziesz ich używać od |
|---|
| 158 | | samego początku, niż zmieniał kod na końcu pisania aplikacji. Jednak w tym tutorial'u |
|---|
| | 154 | .. _dokumentacji URL dispatchera: http://www.djangoproject.com/documentation/url_dispatch#reverse |
|---|
| | 155 | |
|---|
| | 156 | Użyj widoków generycznych - im mniej kodu tym lepiej |
|---|
| | 157 | ==================================================== |
|---|
| | 158 | |
|---|
| | 159 | Widoki ``detail()`` (z `tutoriala nr 3`_) oraz ``results()`` są po prostu niemiłosiernie |
|---|
| | 160 | proste -- i jak wspomniano wczesniej -- nadmiarowe. Widok ``index()`` (także z |
|---|
| | 161 | tutoriala nr 3), który wyświetla listę ankiet, jest podobny. |
|---|
| | 162 | |
|---|
| | 163 | Te widoki wykonują często powtarzane czynności w aplikacji WWW: pobranie danych |
|---|
| | 164 | z bazy danych zgodnie z parametrem przekazanym w adresie URL, załadowanie szablonu |
|---|
| | 165 | oraz zwrócenie przetworzonego szablonu. Ponieważ jest to tak często wykonywane, |
|---|
| | 166 | Django dostarcza skrót nazywany systemem "widoków generycznych". |
|---|
| | 167 | |
|---|
| | 168 | Widoki generyczne są abstrakcją do punktu, w którym nie musisz nawet pisać |
|---|
| | 169 | kodu w Pythonie, aby napisać aplikację. |
|---|
| | 170 | |
|---|
| | 171 | Przeróbmy teraz naszą aplikację ankiet, aby używała systemu widoków generycznych. |
|---|
| | 172 | Możemy więc skasować trochę kodu, który napisaliśmy wcześniej. Musimy tylko wykonać |
|---|
| | 173 | kilka kroków, aby dokonać tej konwersji. |
|---|
| | 174 | |
|---|
| | 175 | .. admonition:: Dlaczego zmieniamy kod w ten sposób? |
|---|
| | 176 | |
|---|
| | 177 | Ogólnie, gdy piszesz aplikacje w Django, musisz ocenić czy widoki generyczne |
|---|
| | 178 | są dobrym rozwiązaniem Twojego problemu. Jeżeli tak, to będziesz ich używać od |
|---|
| | 179 | samego początku niż zmieniał kod na końcu pisania aplikacji. Jednak w tym tutorialu |
|---|
| 191 | | Używamy tutaj dwóch widoków generycznych: ``object_list`` oraz ``object_detail``. Te dwa widoki sa abstrakcja koncepcji "wyswietl liste obiektów" oraz "wyświetl stronę ze szczególami dla konkretnego typu obiektu". |
|---|
| 192 | | |
|---|
| 193 | | * Każdy widok generyczny musi wiedzieć na jakich danych będzie działać. Te dane podaje się w słowniku. Klucz ``queryset`` w tym słowniku wskazuje na listę obiektów, które będa manipulowane przez generyczny widok. |
|---|
| 194 | | |
|---|
| 195 | | * Widok generyczny ``object_detail`` oczekuje wartości ID przekazanej z URL'a, która nazywa się ``"object_id"``, wiec zmieniliśmy ``poll_id`` na ``object_id`` dla widoków generycznych. |
|---|
| 196 | | |
|---|
| 197 | | * Dodaliśmy nazwę ``poll_results``, do widoku wyników, aby mieć możliwość odwołania się do jego URL'a w późniejszym czasie (zobacz dokumentacje na temat `konfigurowania wzorców URL'li`_ aby uzyskać więcej informacji). |
|---|
| 198 | | |
|---|
| 199 | | Używamy tutaj także funkcji `url()`_ z pakietu ``django.conf.urls.defaults``. Jest to dobry zwyczaj |
|---|
| 200 | | aby używać ``url()`` kiedy podaje wzorzec taki jak tutaj. |
|---|
| 201 | | |
|---|
| 202 | | .. _konfigurowania wzorców URL'li: ../url_dispatch/#naming-url-patterns |
|---|
| | 213 | Używamy tutaj dwóch widoków generycznych: ``object_list`` oraz |
|---|
| | 214 | ``object_detail``. Te dwa widoki sa abstrakcją koncepcji "wyświetl listę |
|---|
| | 215 | obiektów" oraz "wyświetl stronę ze szczegółami dla konkretnego typu obiektu". |
|---|
| | 216 | |
|---|
| | 217 | * Każdy widok generyczny musi wiedzieć na jakich danych będzie działać. |
|---|
| | 218 | Te dane podaje się w słowniku. Klucz ``queryset`` w tym słowniku wskazuje |
|---|
| | 219 | na listę obiektów, które będa obsługiwane przez generyczny widok. |
|---|
| | 220 | |
|---|
| | 221 | * Widok generyczny ``object_detail`` oczekuje wartości ID przekazanej z adresu |
|---|
| | 222 | URL, która nazywa się ``"object_id"``, wiec zmieniliśmy ``poll_id`` na |
|---|
| | 223 | ``object_id`` dla widoków generycznych. |
|---|
| | 224 | |
|---|
| | 225 | * Dodaliśmy nazwę ``poll_results`` do widoku wyników, aby mieć możliwość |
|---|
| | 226 | odwołania się do jego adresu URLa w późniejszym czasie (zobacz dokumentację |
|---|
| | 227 | na temat `konfigurowania wzorców adresów URL`_, aby uzyskać więcej informacji). |
|---|
| | 228 | |
|---|
| | 229 | Używamy tutaj także funkcji `url()`_ z pakietu ``django.conf.urls.defaults``. |
|---|
| | 230 | Jest to dobry zwyczaj, aby używać ``url()`` kiedy podaje się wzorzec taki, jak tutaj. |
|---|
| | 231 | |
|---|
| | 232 | .. _konfigurowania wzorców adresów URL: ../url_dispatch/#naming-url-patterns |
|---|
| 214 | | Ponieważ mamy więcej niż jeden wpis w URLconf który używa ``object_detail`` |
|---|
| 215 | | dla aplikacji polls, określamu recznie nazwę szablonu dla widoku wyników: |
|---|
| 216 | | ``template_name='polls/results.html'``. W przeciwnym razie obydwa widoki używały by takiego samego szablonu. |
|---|
| 217 | | Zauwarz że używamy ``dict()`` aby zwrócić zmieniony słownik w tym miejscu. |
|---|
| | 244 | Ponieważ mamy więcej niż jeden wpis w URLconf, który używa ``object_detail`` |
|---|
| | 245 | dla aplikacji polls, określamy recznie nazwę szablonu dla widoku wyników: |
|---|
| | 246 | ``template_name='polls/results.html'``. W przeciwnym razie obydwa widoki używałyby |
|---|
| | 247 | takiego samego szablonu. Zauważ, że używamy ``dict()``, aby zwrócić w tym miejscu |
|---|
| | 248 | zmieniony słownik. |
|---|
| 245 | | aby odpowiadał nowemu kontekstowi zmiennych. W wywołaniu ``render_to_response()``, zmień nazwę zmiennj |
|---|
| 246 | | ``poll`` na ``object``. |
|---|
| 247 | | |
|---|
| 248 | | Ostania rzecz do zrobienia to naprawa obsługi URL'i z uwzględnieniem użycia widoków generycznych. |
|---|
| 249 | | W widoku vote powyrzej, użylismy funkcji ``reverse()``, aby uniknąć sztywnego wpisywania URL'i w widokach. |
|---|
| 250 | | Teraz przełączyliśmy się na widok generyczny, musimy zmienić wywołanie ``reverse()`` aby wskazywało spowrotem do naszego widoku generycznego. Nie możemy już poprostu użyć funkcji widoku -- widoki genryczne mogą (i są) używane wielokrotnie -- |
|---|
| 251 | | ale możemy użyć nazwy której użyliśmy:: |
|---|
| | 276 | aby odpowiadał nowemu kontekstowi zmiennych. W wywołaniu ``render_to_response()``, |
|---|
| | 277 | zmień nazwę zmiennej ``poll`` na ``object``. |
|---|
| | 278 | |
|---|
| | 279 | Ostania rzecz do zrobienia to naprawa obsługi adresów URL z uwzględnieniem użycia |
|---|
| | 280 | widoków generycznych. W widoku vote powyżej użyliśmy funkcji ``reverse()``, |
|---|
| | 281 | aby uniknąć sztywnego wpisywania adresów URL w widokach. Teraz przełączyliśmy się |
|---|
| | 282 | na widok generyczny, więc musimy zmienić wywołanie ``reverse()``, aby wskazywało |
|---|
| | 283 | spowrotem do naszego widoku generycznego. Nie możemy już poprostu użyć funkcji widoku |
|---|
| | 284 | -- widoki genryczne mogą (i są) używane wielokrotnie -- ale możemy użyć nazwy, której użyliśmy:: |
|---|
| 255 | | Uruchom teraz server, i użyj Twojej nowej aplikacji ankiet opartej o widoki generyczne. |
|---|
| 256 | | |
|---|
| 257 | | Aby dowiedzieć się więcej o widokach generycznych, zobacz `dokumentacje widoków generycznych`_. |
|---|
| 258 | | |
|---|
| 259 | | .. _dokumentacje widoków generycznych: http://www.djangoproject.com/documentation/generic_views/ |
|---|
| 260 | | |
|---|
| 261 | | Już w krótce |
|---|
| 262 | | ============ |
|---|
| 263 | | |
|---|
| 264 | | Ten tutorial kończy sie w tym momencie. Ale zobacz w krótce po nowe informacje: |
|---|
| | 288 | Uruchom teraz server i użyj nowej aplikacji ankiet opartej o widoki generyczne. |
|---|
| | 289 | |
|---|
| | 290 | Aby dowiedzieć się więcej o widokach generycznych, zobacz `dokumentację widoków generycznych`_. |
|---|
| | 291 | |
|---|
| | 292 | .. _dokumentację widoków generycznych: http://www.djangoproject.com/documentation/generic_views/ |
|---|
| | 293 | |
|---|
| | 294 | Już wkrótce |
|---|
| | 295 | =========== |
|---|
| | 296 | |
|---|
| | 297 | Ten tutorial kończy sie w tym momencie. Ale sięgnij też po inne informacje: |
|---|